简介
锁作为并发共享数据保证一致性的工具,大多数内置锁都是可重入的,也就是说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立刻成功,并且会将这个锁的计数值加1,而当线程退出同步代码时,计数器将会递减,当计数值等于0时,锁释放。如果没有可重入锁的支持,在第二次企图获得锁时将会进入死锁状态。
Java中提供可重入锁类:ReentrantLock。
测试
- 正常使用时的可重入锁
code:
/**
* 可重入锁测试
* @author dxt
*
*/
public class LockTest {
public void test(){
//第一次获得锁
synchronized(this){
while(true){
//第二次获取锁,如果不可重入,则会死锁
synchronized(this){
System.out.println("可重入锁");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
new LockTest().test();
}
}
- 实现不可冲入锁
/**
* 实现不可重入锁:锁不可以延续使用
* @author dxt
*
*/
public class LockTest02 {
Lock lock = new Lock();
public void a(){
lock.lock(); //第一重锁
b();
lock.unlock();
}
public void b(){
lock.lock(); //第二重锁。会产生死锁
System.out.println("b");
lock.unlock();
}
public static void main(String[] args){
LockTest02 lt = new LockTest02();
lt.a(); //死锁,程序会一直等待
}
}
/**
* 不可重用锁
* @author dxt
*
*/
class Lock{
//是否占用
private boolean isLocked = false;
//使用锁
public synchronized void lock(){
//被加锁后,不能使用,只好等待
while(isLocked){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true; //如果能访问到它,就加上锁,用完之前不释放
}
//释放锁
public synchronized void unlock(){
isLocked = false;
notifyAll();
}
}
- 实现可重入锁:锁可以连续且有计数器
/**
* 实现可重入锁
* @author dxt
*
*/
public class LockTest03 {
ReLock relock = new ReLock();
public void a(){
relock.lock(); //第一重锁
b();
relock.unlock();
}
public void b(){
relock.lock(); //第二重锁。会产生死锁
System.out.println("b"); //一些操作
relock.unlock();
}
public static void main(String[] args){
LockTest03 lt = new LockTest03();
lt.a(); //死锁,程序会一直等待
}
}
/**
* 不可重用锁
* @author dxt
*
*/
class ReLock{
//是否占用
private boolean isLocked = false;
Thread lockedBy = null; //存储线程
private int holdCount = 0;
//使用锁
public synchronized void lock(){
//被加锁后,不能使用,只好等待
Thread t = Thread.currentThread();
while(isLocked && lockedBy != t){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true; //如果能访问到它,就加上锁,用完之前不释放
lockedBy = t;
holdCount++;
//在lock()后可以对临界资源进行处理
}
//释放锁
public synchronized void unlock(){
if(Thread.currentThread() == lockedBy){
holdCount--;
if(holdCount == 0){
isLocked = false;
notifyAll();
lockedBy = null;
}
}
}
}