一般我们都比较喜欢使用synchronized关键字来实现同步,因为这样需要写的代码很少,而且出现错误的可能性还比较低。
所以特殊时候才会用显示创建锁,比如在使用synchronized时出现了异常,程序会抛出异常,但没有机会去执行清理操作了。这时就可以使用Lock配合finally进行系统维护。
使用显示的lock对象 ,有几种方式
lock()
tryLock()//会返回一个boolean值,表示是否取到锁
tryLock(long arg0, TimeUnit arg1) //案例 tryLock(2, TimeUnit.SECONDS) ;//取两秒的锁,两秒后没取到就放弃;也会返回boolean值
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class AttemptLocking {
//显示的使用Lock需要使用这个子类
private Lock lock = new ReentrantLock();
//没有超时机制的trylock
public void untimed() {
boolean captured = lock.tryLock();
try {
System.out.println("tryLock: " + captured);
} finally {
if(captured) {
lock.unlock();
System.out.println("unlock");
}
}
}
//使用超时机制的trylock
public void timed() {
boolean captured = false;
try {
captured = lock.tryLock(2, TimeUnit.SECONDS);//单位为秒 值是2
System.out.println("tryLock(2, TimeUnit.SECONDS): " + captured);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(captured) {
lock.unlock();
System.out.println("unlock");
}
}
}
public static void main(String[] args) throws InterruptedException {
final AttemptLocking locking = new AttemptLocking();
locking.untimed();
locking.timed();
System.out.println("====================");
new Thread(new Runnable() {
@Override
public void run() {
//取得锁之后停1秒再释放锁
locking.lock.lock();
System.out.println("Thread 2 hold lock");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
locking.lock.unlock();
}
}).start();
//让线程2有充足的时间取得锁
Thread.yield();
Thread.sleep(1000);
//再次尝试取锁
locking.untimed();
locking.timed();
}
}
输出结果
tryLock: true
unlock
tryLock(2, TimeUnit.SECONDS): true
unlock
====================
Thread 2 hold lock
tryLock: false
tryLock(2, TimeUnit.SECONDS): true
unlock
在main函数的开始,分别尝试了两种方式取锁,都成功了。
为了体现不同,接下来我让一个线程2先去获得锁,然后1秒后释放。
这这段时间,再用两种方式去取锁,结果很明显,有超时机制的成功了。(等待得到了真爱