ReentrantLock可重入锁

什么是可重入性:线程可以进入任何一个他已经拥有锁的对象所锁住的代码块。

先举个例子看看普通锁:

    public class unReentrantLock {
       private boolean isLock=false;//标志是否加锁
       public synchronized void lock() throws InterruptedException{
       /*
      isLock为true的话,说明这个对象已经被锁住了,这个时候执行while内的方法,通过调用
       wait方法让调用该方法的线程进入等待队列。
       至于用while,不用if,是防止虚假唤醒
       虚假唤醒:obj.wait()除了在obj.notify()和obj.notifyAll()以外,还会在其他某些情况下被唤醒,而这个时候不应该被唤醒。
       用while后就能反复检查进入的临界条件是否满足
        */
       while(isLock){
           wait();
       }

       isLock=true;//如果对象没有被锁住,才会执行到这,这时致它为true,相当于是这个对象被加锁。
       }
       public synchronized void unlock(){
       isLock=false;//使他为false,相当于解锁。这个线程放开了对这个对象的拥有权
       notify();//通知等待队列中的某个线程出队。
       }
    }

    public class unReentrant {
        private unReentrantLock lock = new unReentrantLock();
        private int count = 0;
        public void lockA() throws InterruptedException {
            lock.lock();//锁住lock对象,当其他线程执行到这,因为无法获得lock对象的锁,就会阻塞,就无法对下面的临界区进行操作
        /**
         *这个操作是分步进行的,先取count的值,再加一,如果不加锁,多个线程同时进行,结果就会超过预计,所以加锁,
         * 保证只有一个线程访问他。
         */
        this.count++;
        lock.unlock();//执行结束后释放锁
    }
    public void lockB() throws InterruptedException {
        lock.lock();//例如线程A锁住lock对象,islock被致为true
        /**
         * 到这里线程A想调用lockA方法,但是islock已经为true,因为线程A自己已经锁住这个对象一次了,
         * 所以线程A也无法进入临界区。如果用过synchronized,会发现他没有这个问题,因为他是可重入锁
         */
        lockA();
        lock.unlock();
    }
    }

普通的锁无法使同一线程多次访问被锁住的对象,所以这里引入可重入锁。
接着看例子:

    public class ReentrantLock {
        private boolean isLock = false;//标志是否加锁
        Thread isCurrentThread = null;//用来判断是否是当前线程访问锁对象
        int lockCount = 0;//用来统计同一个线程重复对一个锁对象加锁的次数

        public synchronized void lock() throws InterruptedException {
            Thread currentThread = Thread.currentThread();//获取当前线程
            /**
             * 除了isLock为true,即这个对象被锁住外,还需要同时满足这个这个线程不是当前线程,
             * 所以如果是当前线程再次访问这个锁对象时,虽然islock为true,但是第二个条件不满足,
             * 依旧while中语句。
             */
            while (isLock && isCurrentThread != currentThread) {
                wait();
            }

            isLock = true;//设置isLock为true,相当于进行加锁
            isCurrentThread = currentThread;//将IsCurrentThread至为当前线程
            lockCount++;//当前线程对该锁对象加锁的数量加1;

        }

        public synchronized void unlock() {
            if (Thread.currentThread() == this.isCurrentThread) {//如果调用该方法的线程是当前线程
                lockCount--;//数量减一
                if (lockCount == 0) {//如果加在当前线程上的锁减到0
                    isLock = false;//使他为false,相当于解锁。这个线程放开了对这个对象的拥有权
                    notify();//通知等待队列中的某个线程出队。
                }
            }
        }
    }

java当中的synchroized和java.util.concurrent.locks.ReentrantLock都是可重入锁

猜你喜欢

转载自blog.csdn.net/wang__wang666/article/details/77938273