java读写锁实现原理_java可重入锁原理

java读写锁实现原理_java可重入锁原理一、synchronized和ReentrantLock的对比到现在,看到多线程中,锁定的方式有2种:synchronized和ReentrantLock。两种锁定方式各有优劣,下面简单对比一下:1、synchronized是关键字,就和if…else…一样,是语法层面的实现,因此synchronized获取锁以及释放锁都是Java虚拟机帮助用户完成的;ReentrantLock是类层面的…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、

synchronized和ReentrantLock的对比

到现在,看到多线程中,锁定的方式有2种:synchronized和ReentrantLock。两种锁定方式各有优劣,下面简单对比一下:

1、synchronized是关键字,就和if…else…一样,是语法层面的实现,因此synchronized获取锁以及释放锁都是Java虚拟机帮助用户完成的;ReentrantLock是类层面的实现,因此锁的获取以及锁的释放都需要用户自己去操作。特别再次提醒,ReentrantLock在lock()完了,一定要手动unlock()

2、synchronized简单,简单意味着不灵活,而ReentrantLock的锁机制给用户的使用提供了极大的灵活性。这点在Hashtable和ConcurrentHashMap中体现得淋漓尽致。synchronized一锁就锁整个Hash表,而ConcurrentHashMap则利用ReentrantLock实现了锁分离,锁的知识segment而不是整个Hash表

3、synchronized是不公平锁,而ReentrantLock可以指定锁是公平的还是非公平的

4、synchronized实现等待/通知机制通知的线程是随机的,ReentrantLock实现等待/通知机制可以有选择性地通知

5、和synchronized相比,ReentrantLock提供给用户多种方法用于锁信息的获取,比如可以知道lock是否被当前线程获取、lock被同一个线程调用了几次、lock是否被任意线程获取等等

总结起来,我认为如果只需要锁定简单的方法、简单的代码块,那么考虑使用synchronized,复杂的多线程处理场景下可以考虑使用ReentrantLock。当然这只是建议性地,还是要具体场景具体分析的。

最后,查看了很多资料,JDK1.5版本只有由于对synchronized做了诸多优化,效率上synchronized和ReentrantLock应该是差不多。

二、读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可。如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁,一个写锁

线程进入读锁的前提条件:

没有其他线程的写锁,

没有写请求或者有写请求,但调用线程和持有锁的线程是同一个

线程进入写锁的前提条件:

没有其他线程的读锁

没有其他线程的写锁

到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限。它和后者都是单独的实现,彼此之间没有继承或实现的关系。然后就是总结这个锁机制的特性了:

(a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。

(b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.

(c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。

(d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。

(e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出UnsupportedOperationException异常。

示例:读锁,写锁及读写锁的缓存机制:

/*** 读写锁实现

* 读写锁的缓存机制*/

//缓存的map

private Map map = new HashMap();//读写锁对象

private ReadWriteLock readWriteLock = newReentrantReadWriteLock();private String data=”1″;/*** 进行读操作

* 可以多个读线程同时进入,写线程不能执行*/

publicString getReadWriteLock(String tt) {//获取读锁,并加锁

Lock readLock =readWriteLock.readLock();

readLock.lock();try{

System.out.println(“线程名称:”+Thread.currentThread().getName() + ” be ready to read data!”);//Thread.sleep((long) (Math.random() * 3000));

Thread.sleep(3000);//this.data =tt;

this.data =mainDao.getData(tt);

System.out.println(Thread.currentThread().getName()+ “——->>>>have read data :”+data );return this.data;

}catch(InterruptedException e) {

e.printStackTrace();

}finally{//!!!!!!注意:锁的释放一定要在trycatch的finally中,因为如果前面程序出现异常,锁就不能释放了//释放读锁

readLock.unlock();

}return null;

}/*** 进行写操作

* 只能一个写线程进入,读线程不能执行*/

public voidputReadWriteLock(String data){//获取写锁,并加锁

Lock writeLock =readWriteLock.writeLock();

writeLock.lock();try{

System.out.println(“线程名称:”+Thread.currentThread().getName() + ” be ready to write data!”);

Thread.sleep(3000);this.data =data;

System.out.println(Thread.currentThread().getName()+ ” have write data: ” +data);

}catch(InterruptedException e) {//e.printStackTrace();

System.out.println(“error!!!”);

}finally{//释放写锁

writeLock.unlock();

}

}/*** 设计一个缓存系统

* 读写锁的应用。

* JDK1.5自带的读写锁特性,读与读不互斥,读与写互斥,写与写互斥。

* 为什么要使用读写锁?一句话概括那就是提高系统性能,如何提高呢?

* 试想,对于所有对读的操作是不需要线程互斥的,而如果方法内

* 使用了synchronized关键字同步以达到线程安全,对于所有的线程不管是读还是写的操作都要同步。

* 这时如果有大量的读操作时就会又性能瓶颈。

*

* 所以,当一个方法内有多个线程访问,并且方法内有读和写读操作时,

* 提升性能最好的线程安全办法时采用读写锁的机制对读写互斥、写写互斥。这样对于读读就没有性能问题了

*@authorzhurudong

**/

public voidreadWriteMathod(String key){

readWriteLock.readLock().lock();//读锁,只对写的线程互斥//String key = “tt”;

Object value = null;try{//尝试从缓存中获取数据

value =map.get(key);if (value == null) {

readWriteLock.readLock().unlock();//发现目标值为null,释放掉读锁

readWriteLock.writeLock().lock();//发现目标值为null,需要取值操作,上写锁

try{

value= map.get(key);//很严谨这一步。再次取目标值

if (value == null) {//很严谨这一步。再次判断目标值,防止写锁释放后,后面获得写锁的线程再次进行取值操作//模拟DB操作

value = new Random().nextInt(10000) + “test”;

map.put(key, value);

System.out.println(“db completed!”);

}

readWriteLock.readLock().lock();//再次对读进行锁住,以防止写的操作,造成数据错乱

} finally{/** 先加读锁再释放写锁读作用:

* 防止在100行出多个线程获得写锁进行写的操作,所以在写锁还没有释放前要上读锁*/readWriteLock.writeLock().unlock();

}

}

}finally{

readWriteLock.readLock().unlock();

}

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/169979.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java static关键字的作用_java中static关键字的作用是什么

    java static关键字的作用_java中static关键字的作用是什么java中static关键字的作用:1、java中可以通过statin关键字修饰变量达到全局变量的效果;2、static修饰的方法属于类方法,不需要创建对象就可以调用;3、static代码块常用于初始化静态变量。本文操作环境:windows10系统、java1.8、thinkpadt480电脑。java中static关键字的作用:在java语言中有四种使用情况:成员变量、成员方法、代码块和内部…

  • html中table表格里的内容如何居中「建议收藏」

    html中table表格里的内容如何居中「建议收藏」1.table表格整个居中<divstyle=”text-align:center;”><tableborder=”1″style=”margin:auto;”width=’60%’>……</table></div>我们在table外围div中加入样式style=”text-align:center;”,会发现table表格居中不生效,原因最后说。所以我们在<tableb…

  • 数据挖掘复习(包括一些课本习题)[通俗易懂]

    数据挖掘复习(包括一些课本习题)[通俗易懂]第一章1.数据挖掘定义 在大量的数据中提取潜在有用的信息的过程2.任务分类,聚类,关联,离群点3.对象孔家数据库,时间序列数据库,流数据,多媒体数据库,文本数据,万维网4.知识发现(1)数据清洗(2)数据集成(3)数据转换(4)数据挖掘(5)模式评估(6)知识表示第二章(1)数据挖掘中使用的数据是数据对象及其属性的集合,属性为对象的特性(1)类属性和数值属性,标称,序数,区间,比例数据预处理(1)数据清理(2)数据集成(3)数据变换(4)数据规约(5)离

  • e.Row.Attributes.Add「建议收藏」

    e.Row.Attributes.Add「建议收藏」其实看到属性这个单词,还有点发憷呢,C#里面有个关键词是Attributes,搞了半天貌似没有弄清楚e.Row.Attributes.Add()函数的介绍,包括参数,什么是Attributes就是往行里面添加属性相当于html里面的一个表里的一个行的属性,你看看那个属性有什么,这个就可以添加什么属性//这个就是在前台添加一个Button的按钮,然后给他添加事件<asp…

  • c和Java的区别[通俗易懂]

    c和Java的区别[通俗易懂] 转 c和Java的区别 2017年12月24日20:45:32 lzr_jead 阅读数:166 Java和C语言的区别在哪里?设…

  • leavecriticalsection报错_sequence的用法

    leavecriticalsection报错_sequence的用法线程锁的概念函数EnterCriticalSection和LeaveCriticalSection的用法注:使用结构CRITICAL_SECTION需加入头文件#include“afxmt.h”定义一个全局的锁CRITICAL_SECTION的实例和一个静态全局变量CRITICAL_SECTIONcs;//可以理解为锁定一个资源statici

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号