Java------多线程_高级主题_可重入锁_原理实现(十六)
可重入锁:
锁作为并发共享数据保证一致性的工具,大多数内置锁都是可重入的,也就是说,如果某个线程试图获取一个已经由它自己持有的锁时,那么这个请求会立刻成功,并且会将这个锁的计数值加1,而当线程推出同步代码块时,计数器会递减,当数值等于0时,锁释放,如果没有可重入的支持,在第二次企图获得锁时,将会进入死锁状态,可重入锁随处可见。
案例一:可重入锁
package cooperation;
/**
* 可重入锁:锁可以延续使用
*/
public class ThreadLock01 {
public void test() throws InterruptedException {
//第一次获得锁
synchronized (this){
//第二次获得同样的锁
while (true){
synchronized (this){
System.out.println("可重入锁");
}
Thread.sleep(1000);
}
}
}
public static void main(String[] args) throws InterruptedException {
new ThreadLock01().test();
}
}
案例二:模拟不可重入锁,a方法调用b方法,会一直进行等待,
package cooperation;
/**
* 不可重入锁:锁不可以延续使用
*/
public class ThreadLock02 {
Lock lock = new Lock();
public void a() throws InterruptedException {
lock.lock();
b();
lock.unlock();
}
//此时不可重入
public void b() throws InterruptedException {
lock.lock();
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
new ThreadLock02().a();
}
}
//类:不可重入锁
class Lock{
//是否占用
private boolean isLocked = false;
//使用锁
public synchronized void lock() throws InterruptedException {
if (isLocked){
System.out.println("正在等待");
//等待
wait();
}else {
System.out.println("表明该锁被占用");
isLocked = true;
}
}
//释放锁
public synchronized void unlock(){
isLocked = false;
//唤醒
notify();
}
}
案例三:将案例二的不可重入锁,改写为可重入锁,需要用到计数器表明,该锁已重入次数,以及存储线程,证明锁的调用对象
package cooperation;
/**
* 不可重入锁:锁不可以延续使用
*/
public class ThreadLock03 {
ReLock lock = new ReLock();
public void a() throws InterruptedException {
lock.lock();
b();
lock.unlock();
}
//此时不可重入
public void b() throws InterruptedException {
lock.lock();
lock.unlock();
}
public static void main(String[] args) throws InterruptedException {
new ThreadLock03().a();
}
}
//改写,可重入锁
class ReLock{
//是否占用
private boolean isLocked = false;
//存储线程
Thread lockedBy = null;
//计数器
private int holdCount = 0;
//使用锁
public synchronized void lock() throws InterruptedException {
Thread thread = Thread.currentThread();
if (isLocked && lockedBy != thread){
System.out.println("正在等待");
//等待
wait();
}else {
System.out.println("加锁");
isLocked = true;
lockedBy = thread;
holdCount ++;
}
}
//释放锁
public synchronized void unlock(){
Thread thread = Thread.currentThread();
if (thread == lockedBy){
holdCount --;
System.out.println("释放锁,计数器为"+holdCount);
if (holdCount ==0){
System.out.println("完全释放锁");
isLocked = false;
//唤醒
notify();
lockedBy =null;
}
}
}
}
JUC包下有个ReentrantLock,案例三就是模拟该类所写。