21.3.2 解决共享资源竞争
Java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持。当任务要执行被synchronized关键字保护的代码片段的时候,它将检查锁是否可用,然后获取锁,执行代码,释放锁。
共享资源一般是以对象的新式存在的内存片段,但也可以是文件、输入/输出端口,或者是打印机。要控制对共享资源的访问,得先把它包装进一个对象。然后把所有要访问这个资源的方法标记为synchronized。
所有对象都自动含有单一的锁(也称为监视器)。当在对象上调用其任意synchronized方法的时候,此对象都被加锁,这时候该对象上的其他synchronized方法只有等到前一个方法调用完毕并释放了锁之后才能被调用。
一个任务可以多次获得对象的锁。如果一个方法在同一个对象上调用了第二个方法,后者又调用了同一个对象上的另一个方法,就会发生这种情况。JVM负责跟踪对象被加锁的次数。每当这个相同的任务在这个对象上获取锁时,计数都会递增。
针对每个类,也有一个锁,所以synchronized static方法可以在类的范围内防止对static数据的并发访问。
21.3.3 volatile关键字
volatile关键字确保了应用中的可视性。如果你将一个域声明为volatile的,那么只要对这个域产生了写操作,那么所有的读操作就都可以看到这个修改。即便使用了本地缓存,情况也如此,volatile域会立即被写入到主存中,而读操作就发生在主存中。
21.3.5 临界区
有时,你只是希望防止多个线程同时访问方法内部的部分代码而不是防止访问整个方法。通过这种方式分离出来的代码段被称为临界区,它也是用synchronized关键字建立。这里,synchronized被用来指定某个对象,此对象的锁被用来对花括号内的代码进行同步控制:
synchronized(syncObject) {
}