标签 ‘ lock ’
饥饿和公平
原文地址 By Jakob Jenkov 翻译 Simon-SZ 校对:方腾飞
如果一个线程因为CPU时间全部被其他线程抢走而得不到CPU运行时间,这种状态被称之为“饥饿”。而该线程被“饥饿致死”正是因为它得不到CPU运行时间的机会。解决饥饿的方案被称之为“公平性” – 即所有线程均能公平地获得运行机会。
下面是本文讨论的主题:
1. Java中导致饥饿的原因:
- 高优先级线程吞噬所有的低优先级线程的CPU时间。
- 线程被永久堵塞在一个等待进入同步块的状态。
- 线程在等待一个本身也处于永久等待完成的对象(比如调用这个对象的wait方法)。
2. 在Java中实现公平性方案,需要:
- 使用锁,而不是同步块。
- 公平锁。
- 注意性能方面。 阅读全文
嵌套管程锁死
原文链接 作者:Jakob Jenkov
译者:余绍亮 校对:丁一
嵌套管程锁死类似于死锁, 下面是一个嵌套管程锁死的场景:
线程1获得A对象的锁。 线程1获得对象B的锁(同时持有对象A的锁)。 线程1决定等待另一个线程的信号再继续。 线程1调用B.wait(),从而释放了B对象上的锁,但仍然持有对象A的锁。 线程2需要同时持有对象A和对象B的锁,才能向线程1发信号。 线程2无法获得对象A上的锁,因为对象A上的锁当前正被线程1持有。 线程2一直被阻塞,等待线程1释放对象A上的锁。 线程1一直阻塞,等待线程2的信号,因此,不会释放对象A上的锁, 而线程2需要对象A上的锁才能给线程1发信号……
深入理解Java内存模型(五)——锁
本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-memory-model-5
锁的释放-获取建立的happens before 关系
锁是java并发编程中最重要的同步机制。锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息。下面是锁释放-获取的示例代码:
class MonitorExample { int a = 0; public synchronized void writer() { //1 a++; //2 } //3 public synchronized void reader() { //4 int i = a; //5 …… } //6 }
假设线程A执行writer()方法,随后线程B执行reader()方法。根据happens before规则,这个过程包含的happens before 关系可以分为两类:
- 根据程序次序规则,1 happens before 2, 2 happens before 3; 4 happens before 5, 5 happens before 6。
- 根据监视器锁规则,3 happens before 4。
- 根据happens before 的传递性,2 happens before 5。
Java中的读/写锁
原文链接 作者:Jakob Jenkov 译者:微凉 校对:丁一
相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。
Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。
以下是本文的主题
- 读/写锁的Java实现(Read / Write Lock Java Implementation)
- 读/写锁的重入(Read / Write Lock Reentrance)
- 读锁重入(Read Reentrance)
- 写锁重入(Write Reentrance)
- 读锁升级到写锁(Read to Write Reentrance)
- 写锁降级到读锁(Write to Read Reentrance)
- 可重入的ReadWriteLock的完整实现(Fully Reentrant ReadWriteLock)
- 在finally中调用unlock() (Calling unlock() from a finally-clause)
Java中的锁
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一
锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂。因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字(译者注:这说的是Java 5之前的情况)。
自Java 5开始,java.util.concurrent.locks包中包含了一些锁的实现,因此你不用去实现自己的锁了。但是你仍然需要去了解怎样使用这些锁,且了解这些实现背后的理论也是很有用处的。可以参考我对java.util.concurrent.locks.Lock的介绍,以了解更多关于锁的信息。
以下是本文所涵盖的主题:
剖析Disruptor:为什么会这么快?(一)锁的缺点
原文:http://ifeve.com/disruptor-locks-are-bad/
作者:Trisha’s 译者:张文灼,潘曦 整理和校对:方腾飞,丁一
Martin Fowler写了一篇非常好的文章,里面不仅提到了Disruptor,而且还解释了Disruptor 如何应用在LMAX的架构里。里面有提及了一些目前没有涉及的概念,但最经常问到的问题是 “Disruptor究竟是什么?"。
目前我正准备在回答这个问题,但首先回答"为什么它会这么快?"
这些问题持续出现,但是我不能没有说它是干什么的就说它为什么会这么快,不能没有说它为什么这样做就说它是什么东西。
所以我陷入了一个僵局,一个如何写博客的僵局。
要打破这个僵局,我准备以最简单方式回答第一个问题,如果幸运的话,在以后博文里,如果需要解释的话我会重新提回:Disruptor提供了一种线程之间信息交换的方式。
作为一个开发者,因为"线程"一词的出现,我的警钟已经敲响,它意味着并发,而并发是困难的。
聊聊并发(二)Java SE1.6中的Synchronized
本文属作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-se-16-synchronized
1 引言
在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。