synchronized、volatile

来源:互联网 发布:淘宝主图优化软件 编辑:程序博客网 时间:2024/06/06 06:36
Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,这两种机制的提出都是为了实现代码线程的安全性。其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低),而且其使用也更容易出错。
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”;与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但是它所能实现的功能也仅是synchronized 的一部分。本文介绍了几种有效使用 volatile 变量的模式,并强调了几种不适合使用 volatile 变量的情形。

1.synchronized(锁)
锁提供了两种主要的特性:互斥和可见性。
*互斥:即一次只允许一个线程持有某个特定的锁。
*可见性:必须确保释放锁之前对共享变量数据做出的更改对于其随后获得该锁的另一个线程是可见的,如果没有同步机制提供的这种可见性,线程看到的共享变量可能是修改前的值或不一致的值,将引发许多问题。

2.volatile关键字
volatile关键字可以看成是另一种“轻量级的“synchronized”,与synchronized快相比,volatile变量所需的编码较少,并且运行时开销也较少,但它所能实现的功能仅是synchronized的一部分。
volatile变量具有synchronized的可见特性,但不具备原子性(线程的互斥)。

*volatile是如何保证可见性的?
答:jvm的内存模型中,每个线程都有自己的工作内存,线程之间通信的主要是通过线程的工作内存和主存之间的同步来实现,每个线程执行完成后,会将工作内存的值同步到主存中,volatile关键字,就意味中这个变量随时会被其他线程修改(不稳定)的,因此不能将它拷贝到线程的工作内存中,直接访主存。索引任何线程对volatile变量进行修改,其他线程能够立即获取其最新的值。

*volatile代替synchronized实现提供理想的线程安全,必须满足下面的条件?
答:多个volatile变量之间或者某个变量的当前值与修改后值之间没有约束,因此单独使用volatile还不足以实现多线程计数器。

3.synchronized和volatile比较总结
volatile与synchronized相比,volatile变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性,如果严格遵循volatile的 使用条件(即volatile变量真正独立于其他volatile变量和自己以前的值),在某些情况下可以使用volatile代替synchronized来简化代码。

附:java实现线程安全的计数器
public class CheesyCounter {
private volatile int value = 0;
public int getValue(){
return value;
}
public synchronized int increment(){
return value++;
}
}

参考文献:
Java 理论与实践: 正确使用 Volatile 变量(http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

1 0
原创粉丝点击