Synchronized可重入锁分析

可重入锁又称递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象必须是同一对象或者class),iphone

不会由于以前已经获取过还没实方而发生阻塞。即同一线程可执行多个持有同一个锁的方法。spa

先来一段代码:线程

public class ReentrantSynchronized {
    public synchronized void firstIPhoneByElectric() {
        System.out.println("第一部iphone充电..." + Thread.currentThread().getName());
        secondIPhoneByElectric();
    }

    public synchronized void secondIPhoneByElectric() {
        System.out.println("第二部iphone充电..." + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        ReentrantSynchronized reentrantSynchronized = new ReentrantSynchronized();
        reentrantSynchronized.firstIPhoneByElectric();
    }

}

就像一个多用充电线能够同时给多部iphone充电,可是不会发生任何冲突和阻塞,也就是第一部iphone能够获取充电线(锁)充电的同时还能够第二部iphone也能够获取充电线(锁)进行充电。code

执行结果以下:对象

 

 

 在上面的代码中,类中的两个方法都被内置锁synchronized修饰,给第一部手机充电的同时(firstIPhoneByElectric方法中)给第二部手机充电(调用了secondIPhoneByElectric方法)。blog

由于充电线时多用的(synchronized是可重入的),因此同一我的给第二部手机充电时能够直接用该多用充电线进行充电(在同一线程在调用secondIPhoneByElectric时能够直接得到递归

当前对象的锁,进入secondIPhoneByElectric进行操做)。ip

设想:该充电线是单用的(若是synchronized不是可重入的),那么给第二部手机充电时必须等到第一部手机充电完成释放充电线后才能进行(当前线程在调用secondIPhoneByElectricget

以前必须将firstIPhoneByElectric获取的锁释放掉),实际上该充电线已经被第一部手机占用,且没法释放,(该对象锁被当前线程所持有,且没法释放),因此此时会出现死锁。同步

这是什么原理呢?

当线程尝试获取锁时,可重入锁先尝试获取并更新status值,若是status == 0表示没有其余线程在执行同步代码,则把status置为1,当前线程开始执行。若是status != 0,

则判断当前线程是不是获取到这个锁的线程,若是是的话执行status+1,且当前线程能够再次获取锁。而非可重入锁是直接去获取并尝试更新当前status的值,若是status != 0

的话会致使其获取锁失败,当前线程阻塞。

释放锁时,可重入锁一样先获取当前status的值,在当前线程是持有锁的线程的前提下。若是status-1 == 0,则表示当前线程全部重复获取锁的操做都已经执行完毕,

而后该线程才会真正释放锁。而非可重入锁则是在肯定当前线程是持有锁的线程以后,直接将status置为0,将锁释放。

相关文章
相关标签/搜索