Java------多线程_高级主题_可重入锁_原理实现(十六)

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,案例三就是模拟该类所写。

猜你喜欢

转载自blog.csdn.net/cz_chen_zhuo/article/details/121899454