基本上所以的并发模式在解决线程冲突的问题时,都采用序列化共享资源方案。
锁语句产生了互斥效果,通常把这种机制叫做互斥量。
synchronized
- Java中使用关键字synchronized,为解决资源冲突提供了内置支持。
- 当某个任务对synchronized方法调用,在方法返回之前其它线程调用到synchronized标记的方法时都会阻塞。
- 在使用并发时,将域设为private很重要,否则synchronized不能保证其他任务直接访问域,这样会产生冲突。
- 只有第一个获得锁的线程可以获得第二个锁,每得到一个锁,计数递增,每有一个任务离开synchronized方法,计数递减。当计数为零,锁完全释放,其它线程才可以使用此资源。
lock-显示的互斥机制
java.util.concurrent.locks包中的互斥机制。
缺点:Lock必须被显示的创建,锁定和释放。与内建的锁形式相比缺乏优雅性。
优点:可以尝试获得锁,设置尝试时间。超过时间可以在finally里面做一些事情。对于解决某些问题来说,更加的灵活。
原子性与易变性
原子性:可以应用与处Long和Double以外的基本数据类型。因为Long和Double是64位,读取和写入时被分为两个32位,在一个读取和写入之间切换上下文,会导致任务出现不想看到的结果。
Long和Double可以使用关键字volatile获得原子性。
可视性:一个任务的状态可以被别的任务知道。volatile关键字还确保了应用中的可视性。
易变性:没有被volatile修饰的原子操作不必刷新到主存中,因此其他任务在读取该域时也不必看到新值。
如果多个任务同时访问一个域,这个域就应该是volatile。同步也会导致向主存中刷新,因此当用了synchronized的同步方法或语句块保护时就不需要用volatile修饰了。
注意:volatile而不是synchronized的唯一安全情况是类中只有一个可变的域。第一选择还是synchronized关键字,这是最安全的,尝试其它任何方式都是有风险的。
原子类
java SE5引入了AtomicInteger,AtomicLong,AtomicReference等特殊的原子性变量。对常规操作很少排上用场,在调优的时候很有用。
临界区(同步代码块)
使用同步代码块,而不是同步整个方法,减小了同步范围可以显著的提高性能。
synchronied块需要需要一个同步的对象,最合理的方式是使用当前对象。如:synchronized(this)
同一个对象中的如果用的synchronized快引用的是不同对象,运行时不会因为线程不用的锁之间不会引起阻塞。
线程本地存储
java.lang.ThreadLocal
ThradLocal通常设置为静态域存储。现成中用到该对象时,每个现场都分配了自己的存储。