zoukankan      html  css  js  c++  java
  • 可重入锁与不可重入锁

    可重入锁(递归锁)

    定义:可以递归调用的锁(当某个线程执行某个方法已经获得该锁,在方法中可以再次获取该锁,并且不会发生死锁(前提时同一个对象或Class))
    可重入:某个线程已经获得了某个锁,可以再次获取锁而不会出现死锁。

    注意:synchronized和ReentrantLock都时可重入锁。

    不可重入锁

    定义:不可以递归调用的锁(当某个线程执行某个方法已经获得该锁,在方法中再次获取该锁时,会发生阻塞)

    自定义可重入锁

    解释:当一个类中有A,B两个方法都要加锁,A方法中要调用B方法。当线程1执行A方法时会同时获取A,B两把所锁,只有线程1执行完A方法并释放掉这两把锁时,其他线程才能获得锁。

    package juc.lock.Reentrant;
    
    //自定义可重入锁
    public class Lock {
        private boolean isLock = false;//判断当前锁状态,
        private Thread currentThread = null;//当前线程
        private int lockCount = 0;//当前锁的层数
        //加锁方法
        public synchronized void lock(){
            while (isLock && currentThread != Thread.currentThread()){//当第二次加锁时,第二个条件为false
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            isLock = true;
            currentThread = Thread.currentThread();
            lockCount++;
        }
        //解锁方法
        public synchronized void unlock(){
            if (isLock && currentThread == Thread.currentThread()){
                if (--lockCount==0){
                    isLock=false;
                    notify();
                }
            }
        }
    }
    class Test{
    
        Lock lock = new Lock();//自定义可重入锁
    
        public static void main(String[] args) {
            Test test = new Test();
    
            new Thread(()->{
                test.eat();
            },"A").start();
    
            new Thread(()->{
                test.drink();
            },"B").start();
        }
        public void eat(){
            try {
                lock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"->eat");
                Thread.sleep(1000);
                drink();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
    
        }
        public void drink(){
            try {
                lock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"->drink");
            }finally {
                lock.unlock();
            }
        }
    }
    

    运行结果:

    自定义不可重入锁

    解释:当一个类中有多个方法,且这些方法都需要获得并释放锁。但其中的某个方法得到锁之后,其他方法必须等该方法释放锁之后才能有获得锁的机会。

    package juc.lock.nonReentrant;
    
    //自定义不可重入锁
    public class Lock {
        private boolean isLock = false;//判断当前锁状态
        public synchronized void lock(){
            while (isLock){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    		isLock = true;
        }
        public synchronized void unlock(){
            if (isLock){
                isLock = false;
                notify();
            }
        }
    }
    class Test{
        private Lock lock = new Lock();//自定义不可重入锁
    
        public static void main(String[] args) {
            Test test=new Test();
            new Thread(()->{
                test.eat();
            },"A").start();
    
            new Thread(()->{
                test.drink();
            },"B").start();
        }
        public void eat(){
            try {
                lock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"->eat");
    
                Thread.sleep(1000);
    
                drink();//调用drink方法尝试再次获取锁时,由于已经加过锁了,所以isLock为true,因此会一直wait。
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
        public void drink(){
            try {
                lock.lock();
                System.out.println("线程"+Thread.currentThread().getName()+"->drink");
            } finally {
                lock.unlock();
            }
        }
    }
    

    运行结果:

  • 相关阅读:
    土豆案例(display:none和block的应用)
    显示和隐藏
    鼠标经过提高层级案例(margin,相对定位,z-index)
    垂直对齐vertical-align
    表单初始化
    使用定位隐式转换为行内块元素
    清除浮动的方法
    定位的盒子叠放顺序z-index
    FreeRTOS-为什么关中断之后切换进程?
    PowerPC-关闭中断后,还能报sc中断?
  • 原文地址:https://www.cnblogs.com/code-xu/p/14321214.html
Copyright © 2011-2022 走看看