读书人

Java Concurrent Programming (二)

发布时间: 2012-11-03 10:57:43 作者: rapoo

Java Concurrent Programming (2)
2 线程死锁
死锁(dead lock)是指两个或多个线程都有权限访问两个或多个对象,并且每个线程都在已经获得某个对象锁的情况下等待其它线程已经得到的锁。假设线程A持有对象X的锁,并且正在试图获得对象Y的锁,同时,线程B已经拥有对象Y的锁,并在试图获得对象X的锁。此时因为线程互相等待释放锁而彼此都无法继续操作,死锁就产生了。以下是个死锁的例子:


以上程序按照下面的时序执行,就会产生死锁:

2.2 synchronized关键字与volatile关键字
把代码块声明为 synchronized,通常是指该代码具有原子性(atomicity)和可见性(visibility)。原子性,即锁的互斥性,意味着一个线程一次只能执行由一个指定监控对象(lock)保护的代码,从而防止多个线程在更新共享状态时相互冲突。可见性指某一线程对变量所做的更新,当进入由同一监控器(lock)保护的另一个 synchronized 块时,将立刻可以看到这些对变量所做的更新。
volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。volatile变量可以被看作是一种“轻量级的synchronized“,与synchronized块相比,volatile所需的编码较少,并且运行时的开销也小,但是其所能实现的功能仅是synchronized的一部分。volatile变量可用于提供线程安全,但是必须同时满足下面两个条件:
1)对变量的写操作不依赖于当前值。
2)该变量没有包含在具有其他变量的不变式中。
然而,大多数编程情形都会与这两个条件的其中之一冲突,使得 volatile 变量不能像 synchronized 那样普遍适用于实现线程安全。

2.3 Java内存模型
Java Memory Model分为主内存(main memory)和工作内存(working memory)。Java中所有变量都保存在主内存中,供所有线程共享。每个线程都有自己的工作内存,工作内存中保存的是主内存中某些变量的拷贝。线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。内存模型有两个特征:
1)可见性
2)有序性
在JMM中,可见性:通过并发线程修改变量值, 必须将线程变量同步回主存后, 其他线程才能访问到.
在JMM中,有序性:通过Java提供的同步机制或volatile关键字, 来保证内存的访问顺序.
对synchronized:
当线程要进入synchronized时,如果工作存储器在有未映像到主存储器的工作拷贝,该内容就会被强制写入主存储器,因此之前的计算结果就会被全部的写入主存储器内,成为其他线程可以看得见(visible)的状态。当线程欲退出synchronized时,会执行相同与进入synchronized时强制写入主内存储器的处理。
对volatile:
当线程欲引用volatile字段的值时,通常都会发生从主存储器到工作存储器的拷贝操作,而相反,将值指定给写着volatile的字段后,工作存储器的内容通常便会映像到主存储器。


读书人网 >编程

热点推荐