java SE5的java.util.concurrent类库还包含有定义在java.util.concurrent.locks中的显式的互斥机制。Lock对象必须被显示的创建、锁定和释放。
以下用显式的Lock重写了EvenGenerator:
public class MutexEvenGenerator extends IntGenerator{
private int currentEvenValue=0;
private Lock lock=new ReentrantLock();
@Override
public int next() {
// TODO Auto-generated method stub
lock.lock();
try {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
EvenChecker.test(new MutexEvenGenerator());
}
}
MutexEvenGenerator添加了一个被互斥调用的锁,并使用lock()和unlock()方法在next()内部创建了临界资源。而其中的return语句必须放在try子句中,以确保unlock()不会过早发生,从而将数据暴露给第二个任务。
public class AttempLocking {
private ReentrantLock lock=new ReentrantLock();
public void untimed() {
boolean captured=lock.tryLock();
try {
System.out.println("tryLock(): "+captured);
}finally {
if(captured) {
lock.unlock();
}
}
}
public void timed() {
boolean captured=false;
try {
captured=lock.tryLock(2,TimeUnit.SECONDS);
}catch(InterruptedException e) {
throw new RuntimeException(e);
}
try {
System.out.println("tryLock(2,TIMEUNIT.SECONDS): "+captured);
}finally {
if(captured) {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final AttempLocking al=new AttempLocking();
al.untimed();
al.timed();
new Thread() {
public void run() {
al.lock.lock();
System.out.println("aquired");
}
}.start();
// Thread.yield();
Thread.sleep(1000);
al.untimed();
al.timed();
}
}
/*
*tryLock(): true
tryLock(2,TIMEUNIT.SECONDS): true
aquired
tryLock(): false
tryLock(2,TIMEUNIT.SECONDS): false
*/
ReentrantLock允许你尝试着获取但最终未获取锁,这样如果其他人已经获取了这个锁,那你就可以决定离开去执行其它一些东西,而不是等待直至这个锁被释放,就像在untime()方法中看到的那样。在time()中做出了尝试去获取锁,该尝试可以在2秒后失败。
显式的Lock对象在加锁和释放锁方面,相对于内建的synchronized锁来说,还赋予了你更细粒度的控制力。