非阻塞算法的关键思想就是CAS,CAS是compare and set的缩写,也常被称为lock-free或者wait-free,通过把compare和set两个操作原子化,使得不需要使用锁,但是能够解决并发中的资源争用问题。由于CAS常常是一个回退算法+死循环,所以又被称为spin-lock。由于CAS没有使用锁,线程持续执行,又称为非阻塞算法(non-blocking)。术语不统一,但是都差不多表示同一个东西,我都列在这里,方便初学者理解。
CAS通常并发性能会更好,原因有二:
1、CAS由硬件提供指令支持
2、整个思路属于乐观锁定,而不同于其他类型的锁所采用的悲观锁定,大多数并发程序,冲突发生时间较少,所以乐观锁定更高效。
非阻塞算法是当前的一个研究热点,也越来流行。其显著的优势在于避免了锁带来的问题,而其主要缺点在于与等价的有锁算法比较而言,非阻塞算法的实现要复杂一些。在Java中,doug lea为我们带来util.concurrent包,CAS在整个并发框架中深入应用,不单提高了效率(atomic),而且提高了接口可用性(例如CurrentMap的putIfAbsent)。
有人说,CAS这种技术底层框架提供,不需要了解,其实不然,CAS思想可以应用任何地方,包括数据结构、服务接口、数据库应用等等。我这篇文章要讲的内容就是在关系数据库应用中使用CAS思想。
闲话少说,言归正传!
关系数据库数据库提供了"update T set FState = xx where FState = xx",执行这样的SQL,会返回一个更新行数,在jdbc或者odbc或者ADO .NET中都可以获得更新行数。上面的SQL,如果更新行数>0,则是更新成功,否则是没有进行任何更新,这是很典型的CAS。可以说,关系数据库原生支持CAS。
例如,现在有一个表:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->Create Table T_COUNTER (FName VARCHAR, FCOUNT INT)
这个表存储一些计数器,程序需要对其中的一个计数器进行getAndIncrement的操作,实现如下:
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->// incremnt的实现算法在这个方法里
// 三点:外部循环、成功执行操作则退出循环、不成功则重来
public int getAndIncrement(String name) {
for (;;) {
int expectValue = getCurrentValue(name);
int updateValue = expectValue + 1;
if (updateCounter(name, expectValue, updateValue)) return expectValue;
}
}
public boolean updateCounter(String name, int expectValue, int updateValue) {
String sql = "UPDATE T_COUNTER SET FCOUNT = @updateValue WHERE FName = @name AND FCOUNT = @expectValue";
int updateCount = executeUpdate(sql);
return updateCount > 0;
}
public int getCurrentValue(String name) {
// SELECT FCOUNT FROM T_COUNTER WHERE FNAME = @name
// TODO 执行这段SQL,返回FCOUNT的值
return 0;
}
private int executeUpdate(String sql) {
// TODO 执行SQL,返回更新行数
return 0;
}
这样的实现,避免SQL Server中使用locking hints,Oracle、DB2、MySQL中使用select for update长时间锁定T_COUNTER表,性能更好,也更通用。要知道使用locking hints,不同厂商的数据库的实现是不一样的,Oracle和Microsoft SQL Server就相差很大。
这样做的优点:
1、性能更好
2、锁表时间更短
3、基于标准SQL,不同的关系数据库通用
4、上述实现并不复杂
分享到:
相关推荐
简介:Java5.0第一次让使用Java语言开发非阻塞算法成为可能,java.util.concurrent包充分地利用了这个功能。非阻塞算法属于并发算法,它们
:为提高基于SQL Server 数据库应用程序的执行效率,分析了SQL Server 数据库系统自身的查询优化处理技术,总结 出多种基于SQL Server 数据库的应用程序性能优化方法:选择性能优越的服务器;优化数据库设计;使用...
amp, PHP应用程序的非阻塞并发框架 Amp是PHP的一个非阻塞并发框架。 它提供了一个事件循环,承诺和流作为异步编程的基础。生成器结合使用的承诺用于构建协同,这样就可以以像同步代码一样编写异步代码。安装这里...
在应用程序更新过程中被保存的文件 116 Keychain数据 116 获取应用程序目录的路径 117 文件数据的读写 118 文件访问的指导原则 123 保存状态信息 123 大小写敏感性 124 网络 124 有效进行网络通讯的贴士 124 使用Wi-...
sql server 捕获数据库阻塞情况,代码整理
这是封装的socket库,用poll采用非阻塞模式,接收消息与网线断开处理以回调函数方式到应用层处理,使用起来非常方便,带服务端和客户端的测试实例
Hibernate Reactive可以在任何普通Java程序中使用,但特别针对和等React式环境中的使用。 当前支持 , 和 。 要了解更多信息,访问 。 兼容性 Hibernate Reactive已通过以下测试: Java 8 PostgreSQL 13 MySQL...
netius:可读的、简单和快速异步非阻塞的网络应用程序
检查数据发生死锁、阻塞的原因,并根据不同原因解决问题。
adbcj, 在Java中,异步数据库连接 Java中基于的异步数据库连接这是我为我的论文( 在 Brigham大学) 创建... 这里项目有四个 maincomponents:用于异步/非阻塞关系数据库交互的数据库无关 API ( 概念类似于 JDBC ) 。API的
vc++6.0 编写socket多线程例程,非阻塞模式,客户端 服务器端源代码,可运行
mysql 异步示例使用来自 mariadb-connector-c 的非阻塞 API 连接 mysql 数据库的示例。
使用的是达梦7,这个数据库有很多BUG,官方提供的客户端,不仅卡,而且登录了后,使用Java JDBC操作更新时,是会被阻塞的,所以,在使用Java开发达梦应用时候,尽量关闭他客户端。 另外达梦还有个模式的概念,这...
也就是说,在Android应用程序主线程中,所有函数都是在一个消息循环中执行的。Android应用程序其它线程,也可以像主线程一样,拥有消息循环。Android应用程序主线程是一个特殊的线程,因为它同时也是UI线程以及触摸...
*支持JSON格式的请求和响应,对Restful API应用程序开发非常友好; *支持文件下载和上传; *支持gzip,brotli压缩传输; *支持流水线; *提供轻量级的命令行工具drogon_ctl,以简化Drogon中各种类的创建以及视图代码...
源码展示了采用非阻塞模式WinSock编程的服务器和客户端,建立连接后,在服务器窗口输入空格会向所有客户端发送一条字符串消息。 WinSock解决方案下的Client、Server工程分别为服务器和客户端,NetWork工程为稍作封装...
tornado即是一个http非阻塞服务器, 就要用起来, 我们将用到tornado框架 ,mongodb数据库 以及motor(mongodb的异步驱动).来简单实现tornado的非阻塞功能. 其他环境支持的下载与安装 1.安装mongodb $ sudo apt-get ...
脚本查询当前数据库阻塞,阻塞会话事物,进程,锁类型等
根据银行家算法的思想,编写程序,解决并发进程的死锁问题。 本实验要求设计并实现银行家算法。银行家算法是死锁避免的经典算法,其核心思想是:进程动态地申请资源,每次申请资源时系统都执行安全状态检查算法判断...
微信小程序云函数中多次调用云数据库JS源代码,使用await关键字阻塞程序,等两个查询云数据库的代码查询出结果后,再进行后续处理,最后return想要的结果。