查看原文
其他

Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性

徐刘根 Java后端技术 2019-01-09

上一篇:

Java多线程编程-(1)-线程安全和锁Synchronized概念

基本介绍了进程和线程的区别、实现多线程的两种方式、线程安全的概念以及如何使用Synchronized实现线程安全,下边介绍一下关于Synchronized的其他基本特性。

1

Synchronized锁重入

(1)关键字Synchronized拥有锁重入的功能,也就是在使用Synchronized的时候,当一个线程得到一个对象的锁后,在该锁里执行代码的时候可以再次请求该对象的锁时可以再次得到该对象的锁。

(2)也就是说,当线程请求一个由其它线程持有的对象锁时,该线程会阻塞,而当线程请求由自己持有的对象锁时,如果该锁是重入锁,请求就会成功,否则阻塞。

(3)一个简单的例子就是:在一个Synchronized修饰的方法或代码块的内部调用本类的其他Synchronized修饰的方法或代码块时,是永远可以得到锁的,示例代码A如下:

执行结果:

示例代码A向我们演示了,如何在一个已经被synchronized关键字修饰过的方法再去调用对象中其他被synchronized修饰的方法。

(4)那么,为什么要引入可重入锁这种机制哪?

我们上一篇文章中介绍了一个“对象一把锁,多个对象多把锁”,可重入锁的概念就是:自己可以获取自己的内部锁

假如有1个线程T获得了对象A的锁,那么该线程T如果在未释放前再次请求该对象的锁时,如果没有可重入锁的机制,是不会获取到锁的,这样的话就会出现死锁的情况。

就如代码A体现的那样,线程T在执行到method1()内部的时候,由于该线程已经获取了该对象syncDubbo 的对象锁,当执行到调用method2() 的时候,会再次请求该对象的对象锁,如果没有可重入锁机制的话,由于该线程T还未释放在刚进入method1() 时获取的对象锁,当执行到调用method2() 的时候,就会出现死锁。

(5)那么可重入锁到底有什么用哪?

正如上述代码A和(4)中解释那样,最大的作用是避免死锁。假如有一个场景:用户名和密码保存在本地txt文件中,则登录验证方法和更新密码方法都应该被加synchronized,那么当更新密码的时候需要验证密码的合法性,所以需要调用验证方法,此时是可以调用的。

(6)关于可重入锁的实现原理,是一个大论题,在这里篇幅有限不再学习,有兴趣可以移步至:http://www.cnblogs.com/pureEve/p/6421273.html 进行学习。

(7)可重入锁的其他特性:父子可继承性

可重入锁支持在父子类继承的环境中,示例代码如下:


2

Synchronized的其他特性

(1)出现异常时,锁自动释放

就是说,当一个线程执行的代码出现异常的时候,其所持有的锁会自动释放,示例如下:

执行结果如下:

可以看出,当执行代码报错的时候,程序不会再执行,即释放了锁。

(2)将任意对象作为监视器

执行结果:

(3)单利模式-双重校验锁:

单例模式中有一个经典的实现就是:双重校验锁,其中就是用到了synchronized,实现代码如下:



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存