java锁的种类以及辨析(一):自旋锁
作者:山鸡
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
1、自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下
作者:山鸡
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利,但是锁的具体性质以及类型却很少被提及。本系列文章将分析JAVA下常见的锁名称以及特性,为大家答疑解惑。
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下
原文:http://doc.akka.io/docs/akka/2.3.6/general/terminology.html 译者:吴京润
本章我们试图建立一个通用的术语列表,用来定义有关并发和分布式系统的坚实的基础,而这也是akka的目标。请注意,在这些术语当中许多并没有一致的定义。我们简单的寻求在akka文档范围内使用的工作定义。 阅读全文
原文:http://doc.akka.io/docs/akka/2.3.6/intro/use-cases.html 译者:吴京润
我们看到akka正被许多大型组织所采用,已被广泛应用于投资与商业银行业务,零食与社交媒体,虚拟仿真,游戏与博彩,数据分析等等行业。任何需要高吞吐量和低延迟的系统都是使用akka的良好候选者。 阅读全文
原文:http://doc.akka.io/docs/akka/2.3.6/intro/deployment-scenarios.html 译者:吴京润
有两种不同的使用akka的方式:
如果你在构建一个web应用,这可能就是你想要的。在库模式下,通过向模块栈添加越来越多的模块有许多种使用akka的方式。
原文:http://doc.akka.io/docs/akka/2.3.6/java/hello-world.html 译者:吴京润
基于actor在控制台打印这一知名问候的困难在Typesafe Activator教程中名为Akka Main in Java项目中已有介绍。
本教程说明了通用启动器类akka.Main,只接收一个命令行参数:应用的主actor类名。这个main方法将为运行actor创建基础设施,用来启动指定的主actor以及在主actor终止时为关闭整个应用做出安排
Typesafe Activator中有相同问题域的另一个名为Hello Akka!的教程讲述了更深入的akka基础知识。
原文:http://doc.akka.io/docs/akka/2.3.6/intro/getting-started.html 译者:吴京润
AKKA要求你的计算机已经安装了Java1.6或更高版本。
学习AKKA的最好方式是下载Typesafe Activator并尝试一个AKKA模板项目。
有许多种下载AKKA的方式。你可以把它当作Typesafe平台的一部分下载(就像上面描述的)。还可以下载完全发布版,它包含微内核以及所有模块。或者使用像Maven或SBT这样的构建工具从AKKA Maven仓库下载依赖。 阅读全文
Semaphore(信号量)是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。很多年以来,我都觉得从字面上很难理解Semaphore所表达的含义,只能把它比作是控制流量的红绿灯,比如XX马路要限制流量,只允许同时有一百辆车在这条路上行使,其他的都必须在路口等待,所以前一百辆车会看到绿灯,可以开进这条马路,后面的车会看到红灯,不能驶入XX马路,但是如果前一百辆中有五辆车已经离开了XX马路,那么后面就允许有5辆车驶入马路,这个例子里说的车就是线程,驶入马路就表示线程在执行,离开马路就表示线程执行完成,看见红灯就表示线程被阻塞,不能执行。
Semaphore可以用于做流量控制,特别公用资源有限的应用场景,比如数据库连接。假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发的读取,但是如果读到内存后,还需要存储到数据库中,而数据库的连接数只有10个,这时我们必须控制只有十个线程同时获取数据库连接保存数据,否则会报错无法获取数据库连接。这个时候,我们就可以使用Semaphore来做流控,代码如下:
阅读全文
CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。CyclicBarrier默认的构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。
原文:http://doc.akka.io/docs/akka/2.3.6/intro/what-is-akka.htmll 译者:吴京润
可扩展的实时事务处理
我们相信编写并发、容错、可扩展的应用相当的困难。盖因大多数时候我们一直在使用错误的工具和错误的抽象等级。AKKA就是为了改变这一切的。我们利用角色模型提升了抽象等级,并且提供了一个用来构建可扩展的、弹性的以及响应式应用的更好的平台——更多信息请见Reactive Manifesto。对于容错机制我们采用“让它崩溃”模型,这一模型已在电信行业取得了巨大的成功,旨在构建自我修复与永不停机的系统。角色还提供了透明的分布式抽象以及真正的可扩展且容错应用的基础。
AKKA是开源的,并遵守Apache2许可。
请注意所有代码样例的编译,因此如果你想直接访问这些源码,可以去github上访问AKKA文档子项目:Java和Scala。 阅读全文
tomcat在处理每个连接时,Acceptor
角色负责将socket上下文封装为一个任务SocketProcessor
然后提交给线程池处理。在BIO和APR模式下,每次有新请求时,会创建一个新的SocketProcessor
实例(在之前的tomcat对keep-alive的实现逻辑里也介绍过可以简单的通过SocketProcessor
与SocketWrapper
实例数对比socket的复用情况);而在NIO里,为了追求性能,对SocketProcessor
也做了cache,用完后将对象状态清空然后放入cache,下次有新的请求过来先从cache里获取对象,获取不到再创建一个新的。
这个cache是一个ConcurrentLinkedQueue
,默认最多可缓存500个对象(见SocketProperties
)。可以通过socket.processorCache
来设置这个缓存的大小,注意这个参数是NIO特有的。
接下来在SocketProcessor
执行过程中,真正的业务逻辑是通过一个org.apache.coyote.Processor
的接口来封装的,默认这个Processor
的实现是org.apache.coyote.http11.Http11Processor
。我们看一下SocketProcessor.process(...)
方法的大致逻辑:
tomcat的最大连接数参数是maxConnections
,这个值表示最多可以有多少个socket连接到tomcat上。BIO模式下默认最大连接数是它的最大线程数(缺省是200),NIO模式下默认是10000,APR模式则是8192(windows上则是低于或等于maxConnections的1024的倍数)。如果设置为-1则表示不限制。
在tomcat里通过一个计数器来控制最大连接,比如在Endpoint的Acceptor里大致逻辑如下:
对于acceptCount
这个参数,含义跟字面意思并不是特别一致(个人感觉),容易跟maxConnections
,maxThreads
等参数混淆;实际上这个参数在tomcat里会被映射成backlog
:
static {
replacements.put("acceptCount", "backlog");
replacements.put("connectionLinger", "soLinger");
replacements.put("connectionTimeout", "soTimeout");
replacements.put("rootFile", "rootfile");
}
backlog表示积压待处理的事物,是socket的参数,在bind的时候传入的,比如在Endpoint
里的bind方法里:
原文地址 作者:Pedro Ramalhete,译者:叶磊,校对:周可人
在学术论文中Harris Linked List是使用最广泛的并发数据结构之一。
Harris Linked List是一个基于linked-list的并发有序set(或者是map),可进行无锁性质的插入,删除和查找操作。
http://research.microsoft.com/pubs/67089/2001-disc.pdf
这篇文章最早在2001年的DISC会议上发表,作者是Tim Harris,目前在Oracle就职。
原文地址 作者:Pedro Ramalhete,译者:周可人,校对:梁海舰
Tick lock是mutual lock的一种简单实现:
http://web.mit.edu/6.173/www/currentsemester/readings/R06-scalable-synchronization-1991.pdf
它是由John Mellor-Crummey和Michael Scott在1991年提出的(pdf中2.2节),感谢C++11和C11中新的内存模型,我们可以对单个变量进行具有屏障或者不具有屏障的原子操作。当屏障没有使用,只有原子性保证时,我们称之为“relaxed atomic”:
http://en.cppreference.com/w/cpp/atomic/memory_order
注意在C11/C++11内存模型中,一个原子变量并不具有内在的“顺序一致性”或者“relaxed”性质,然而我们可以在每次访问的时选择它的行为。
原子修饰符只能保证原子性,即这个变量会被单步读或写。其他语言,如Java和Scala则不同,它们可以保证几乎所有的原生类型提供原子性保证,从而表现为“relaxed atomic”。并且,所有被声明为顺序一致性的变量可以在整个程序中保持性质(除非在Java中使用sun.misc.unsafe)。尽管这个细微的差异可能看起来并不重要,但是当我们的目标是从同步或是并发算法中挖掘最大性能时,就需要关注这个差异了。