[coolxing按: 转载请注明作者和出处, 如有谬误, 欢迎在评论中指正.]
java.util.concurrent.locks包提供了锁和等待条件的接口和类, 可用于替代JDK1.5之前的同步(synchronized)和监视器机制(主要是Object类的wait(), notify(), notifyAll()方法).
互斥锁--Lock接口及其实现类ReentrantLock
所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别:
public class LockTest {
private static Lock lock = new ReentrantLock();
public static void main(String[] args) {
lock.lock();
invokeMethod();
}
private static void invokeMethod() {
lock.unlock();
}
}
为了确保锁被释放, 通常会采用如下的代码形式:
Lock lock = new ReentrantLock();
// 获取锁
lock.lock();
try {
// access the resource protected by this lock
} finally {
// 释放锁
lock.unlock();
}
|--void lock(): 执行此方法时, 如果锁处于空闲状态, 当前线程将获取到锁. 相反, 如果锁已经被其他线程持有, 将禁用当前线程, 直到当前线程获取到锁.
|--void unlock(): 执行此方法时, 当前线程将释放持有的锁. 锁只能由持有者释放, 如果线程并不持有锁, 却执行该方法, 可能导致异常的发生.
|--boolean tryLock(): 如果锁可用, 则获取锁, 并立即返回true, 否则返回false. 该方法和lock()的区别在于, tryLock()只是"试图"获取锁, 如果锁不可用, 不会导致当前线程被禁用, 当前线程仍然继续往下执行代码. 而lock()方法则是一定要获取到锁, 如果锁不可用, 就一直等待, 在未获得锁之前,当前线程并不继续向下执行. 通常采用如下的代码形式调用tryLock()方法:
Lock lock = new ReentrantLock();
if (lock.tryLock()) {
try {
// manipulate protected state
} finally {
lock.unlock();
}
} else {
// perform alternative actions
}
此用法可确保如果获取了锁, 则会释放锁; 如果未获取锁, 则不会试图将其释放.
条件--Condition
调用Condition对象的相关方法, 可以方便的挂起和唤醒线程. Object对象的wait(), notify(), notifyAll()方法当然也可以做到这一点, 但是Object对象的这些方法存在很不方便的地方--如果多个线程调用了obj的wait()方法而挂起, 那么我们无法做到调用obj的notify()和notifyAll()方法唤醒其中特定的一个线程. 而Condition对象就可以做到这一点. 具体的代码请参见我的上一篇博客http://coolxing.iteye.com/blog/1236696中的解法二部分.
读写锁--ReadWriteLock接口及其实现类ReentrantReadWriteLock
ReentrantReadWriteLock中定义了2个内部类, ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock, 分别用来代表读取锁和写入锁. ReentrantReadWriteLock对象提供了readLock()和writeLock()方法, 用于获取读取锁和写入锁.
使用读写锁的一个例子:
public class ReadWriteLockTest {
private static ReadWriteLock lock = new ReentrantReadWriteLock();
private static Person person = new Person("David Beckham", true);
public static void main(String[] args) {
new Thread() {
public void run() {
while(true) {
try {
lock.readLock().lock();
System.out.print("name = " + person.getName());
System.out.println(", isMan = " + person.isMan());
} finally {
lock.readLock().unlock();
}
}
};
}.start();
new Thread() {
public void run() {
boolean state = true;
while(true) {
try {
lock.writeLock().lock();
if (state) {
person.setName("Lady GaGa");
person.setMan(false);
state = false;
} else {
person.setName("David Beckham");
person.setMan(true);
state = true;
}
} finally {
lock.writeLock().unlock();
}
}
};
}.start();
}
}
class Person {
private String name;
private boolean isMan;
public Person(String name, boolean isMan) {
this.name = name;
this.isMan = isMan;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isMan() {
return isMan;
}
public void setMan(boolean isMan) {
this.isMan = isMan;
}
}
不管程序运行多久, 也不会有人妖的出现.