您的位置:首页 > 编程语言 > Java开发

java并发也许你不知道的一些内容(读Java Concurrency in Practice)(转)

2010-12-03 13:03 337 查看
转自:http://snake1987.javaeye.com/blog/733843

1.线程安全

a.无状态的类是线程安全的

b.所有状态都具有原子性的类是线程安全的

原子性:即对该类的操作是不被打断的,即使在多线程的环境下

如果一个类只有单个状态,推荐使用jdk中的java.util.concurrent.atomic包AtomicBoolean

AtomicInteger

AtomicIntegerArray

AtomicIntegerFieldUpdater

AtomicLong

AtomicLongArray

AtomicLongFieldUpdater

AtomicMarkableReference

AtomicReference

AtomicReferenceArray

AtomicReferenceFieldUpdater

AtomicStampedReference

这些类作为状态都具有原子性

2.Synchronized

a.如果一个方法用Synchronized关键字修饰,则调用该方法所用的锁,为调用方法的对象的固有锁(如反射),如果同时带有Static关键字修饰,则使用的锁为该方法所在的类的固有锁。

固有锁:每个对象都隐性地带有一个锁,该锁为重入锁(重入锁将在后文介绍),用于synchronized关键字

3.重入锁

关于重入锁的解释用书中英文的解释会更准确:But because intrinsic locks are reentrant, if a
thread tries to acquire a lock that it already holds, the request
succeeds.

可能看完上面的还是有点难理解

举一个书中的例子:

看以下代码



假设不是可重入锁,那会出现一个什么现象?

调用super.doSomething()时发现该方法被锁住了,然后等待,但等待的锁自己正持有着,也就变成了死锁

重入锁的实现:

重入锁是通过一个count和记录owner--一个持有该锁的Thread来实现的。当count值为0,认为这个锁当前没被任何线程持有。当
一个线程持有了该锁了,jvm就会把owner置为该线程,并把count置为1,如果同样锁线程再次请求该锁,那jvm就会把count+1,如果线程
退出同步块,则count-1,当count为0时,锁就释放了。

4.线程状态的锁操作

对于每一个涉及到多个变量的不变量,所有涉及到的变量都应该用同一个锁来进行同步

怎么理解呢?

看例子:



在vector中,每个方法都是用synchronized修饰的,但在上面的使用中--如果两个线程先后进入该语句块,再轮流执行
vector.contain(element),显然还是会添加两次同样的element到vector中,所以还是不能保证vector的原子性

5.程序中的代码是可能被打乱的

如果没有进行同步,编译器,进程,和运行环境将有可能会打乱运行的顺序。

如文中所举例子:



将有可能出现这样的状况:输出结果为0.

这是因为执行的顺序被打乱了

6.64位数据的读或写是非原子性的

一般的数据类型,如int,执行

int a = 1;

int b = a;

这些操作都是原子操作,但是像long,double就不是了

jvm是允许把64位数据的读和写分开两次操作的,每次操作32位。

因此,有些项目,我们对某些数据的实时性不会太在意,就不会定义该变量为原子变量,但如果是long或者double类型,就要小心了。很有可能某用户在读取的时候读到的是前一个数据的前32位,和后一个数据的后32位

7.volatile关键字

当一个变量用volatile声明了,编译器会放一个notice到该变量的共享区,然后当执行的时候,就不会对这个变量在程序中的执行顺序进行
修改。并且volatile不会缓存在寄存器中,也不会缓存在别的进程中,因此,读volatile修饰的变量时总能返回一个最新更新的值。

使用锁能同时保证变量的可见性和原子性,但volatile只能保证其可见性。

什么时候不适合使用volatile?

举一个经典的例子:i++操作,在并发环境下volatile是不能保证其正确性的

什么时候可以用volatile?

* 该变量的值不依赖该变量当前的值,像i++,或者你能保证该变量的更新只在单线程的环境下出现

* 该变量不和其他的变量一起包含在一个不变量中,如上文的vector

* 由于其他的原因,该变量不需要使用锁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: