显示锁
基于synchronized关键字的锁机制有以下问题:
· 锁只有一种类型,而且对所有同步操作都是一样的作用
· 锁只能在代码块或方法开始的地方获得,在结束的地方释放
· 线程要么得到锁,要么阻塞,没有其他的可能性
Java 5对锁机制进行了重构,提供了显示的锁,这样可以在以下几个方面提升锁机制:
· 可以添加不同类型的锁,例如读取锁和写入锁
· 可以在一个方法中加锁,在另一个方法中解锁
· 可以使用tryLock方式尝试获得锁,如果得不到锁可以等待、回退或者干点别的事情,当然也可以在超时之后放弃操作
显示的锁都实现了java.util.concurrent.Lock接口,主要有两个实现类:
· ReentrantLock - 比synchronized稍微灵活一些的重入锁
· ReentrantReadWriteLock - 在读操作很多写操作很少时性能更好的一种重入锁
对于如何使用显示锁,可以参考Java面试系列文章《Java面试题集51-70》中第60题的代码。只有一点需要提醒,解锁的方法
unlock的调用最好能够在finally块中,因为这里是释放外部资源最好的地方,当然也是释放锁的最佳位置,因为不管正常异常
可能都要释放掉锁来给其他线程以运行的机会。
CountDownLatch
CountDownLatch是一种简单的同步模式,它让一个线程可以等待一个或多个线程完成它们的工作从而避免对临界资源并发访
问所引发的各种问题。下面借用别人的一段代码(我对它做了一些重构)来演示CountDownLatch是如何工作的。
import java.util.concurrent.CountDownLatch;
/**
* 工人类
*
*/
class Worker {
private String name; // 名字
private long workDuration; // 工作持续时间
/**
* 构造器
*/
public Worker(String name, long workDuration) {
this.name = name;
this.workDuration = workDuration;
}
/**
* 完成工作
*/
public void doWork() {
System.out.println(name + " begins to work...");
try {
Thread.sleep(workDuration); // 用休眠模拟工作执行的时间
} catch(InterruptedException ex) {
ex.printStackTrace();
}