Java并发编程之ReadWriteLock读写锁的操作方法

 更新时间:2021年02月03日 10:29:42   作者:Java硬件工程师  
这篇文章主要介绍了Java并发编程之ReadWriteLock读写锁的操作方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

1.ReadWriteLock介绍

在这里插入图片描述

为什么我们有了Lock,还要用ReadWriteLock呢。我们对共享资源加锁之后,所有的线程都将会等待。Lock读操作也锁,写操作也会锁,而对共享资源读的时候,其实是不用加锁的。当然读写同时存在的情况也会有。
比如我们数据库常用操作有增删改查,增删改都是写操作,写操作必须加锁,而读操作可以共享。不是所有的操作都需要加锁。
为了进一步提高复用性和粒度,写操作独占,读操作共享,不加锁。
ReadWriteLock管理一组锁,一个是只读的锁,一个是写锁。读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的。
即读读可共享,写读写写要独占
读操作不用关心资源争抢和数据一致性的操作

多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源应该可以同时进行。
但是如果有一个线程想去写共享资源来,就不应该再有其它线程可以对该资源进行读或写。
小总结:
  读-读能共存
  读-写不能共存
  写-写不能共存

ReadWriteLock适用于读多写少的并发情况。
Java并发包中ReadWriteLock是一个接口,主要有两个方法,如下:

public interface ReadWriteLock {
 /**
  * 返回读锁
  */
 Lock readLock();

 /**
  * 返回写锁
  */
 Lock writeLock();
}

Java并发库中ReetrantReadWriteLock实现了ReadWriteLock接口并添加了可重入的特性。

2.不用读写锁的案例

class MyCache{
	//volalite保证数据再线程间的可见性和一定的有序性
	private volatile Map<String,Object> map=new HashMap<>();
	public void put(String key,Object value){
		System.out.println(Thread.currentThread().getName()+"\t ---写入数据"+key);
		map.put(key,value);
		try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
		System.out.println(Thread.currentThread().getName()+"\t ---写入完成");
	}
	public void get(String key){
		System.out.println(Thread.currentThread().getName()+"\t 读取数据");
		Object result=map.get(key);
		System.out.println(Thread.currentThread().getName()+"\t 读取完成"+result);
	}
	
}
public class ReadWriteLockDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyCache myCache=new MyCache();
		for(int i=1;i<=5;i++){
			final int tempInt=i;
			new Thread(()->{
				myCache.put(tempInt+"",tempInt+"");
				
			},String.valueOf(i)).start();
		}
		for(int i=1;i<=5;i++){
			final int tempInt=i;
			new Thread(()->{
				myCache.get(tempInt+"");
				
			},String.valueOf(i)).start();
		}	
	}
}

在这里插入图片描述

上面的运行结果出现了一个很严重的问题,比如说,线程1在写入数据的时候,还没等线程1写完,其它线程也在写和读。这违背了事务的原子性。而且也破坏了数据的完整性和一致性,我正在写的时候,不允许其他线程同时也在写或者读。即1写入的时候,必须要满足后一条就是1写入完成。

3.用读写锁的案例

class MyCache{
	//volalite保证数据再线程间的可见性和一定的有序性
	private volatile Map<String,Object> map=new HashMap<>();
	private ReadWriteLock readwritelock=new ReentrantReadWriteLock();
	public void put(String key,Object value){
		readwritelock.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName()+"\t ---写入数据"+key);
			map.put(key,value);
			try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
			System.out.println(Thread.currentThread().getName()+"\t ---写入完成");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally{
			readwritelock.writeLock().unlock();
		}
	}
	public void get(String key){
		readwritelock.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName()+"\t 读取数据");
			Object result=map.get(key);
			System.out.println(Thread.currentThread().getName()+"\t 读取完成"+result);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally{
			readwritelock.readLock().unlock();
		}

	}
	
}
public class ReadWriteLockDemo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyCache myCache=new MyCache();
		for(int i=1;i<=5;i++){
			final int tempInt=i;
			new Thread(()->{
				myCache.put(tempInt+"",tempInt+"");
				
			},String.valueOf(i)).start();
		}
		for(int i=1;i<=5;i++){
			final int tempInt=i;
			new Thread(()->{
				myCache.get(tempInt+"");
				
			},String.valueOf(i)).start();
		}	
	}
}

在这里插入图片描述

到此这篇关于Java并发编程之ReadWriteLock读写锁的文章就介绍到这了,更多相关java ReadWriteLock读写锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用Scala生成随机数的方法示例

    使用Scala生成随机数的方法示例

    这篇文章主要介绍了使用Scala生成随机数的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • Java实现复制文件并命名的超简洁写法

    Java实现复制文件并命名的超简洁写法

    这篇文章主要介绍了Java实现复制文件并命名的超简洁写法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • SpringBoot整合Pulsar的实现示例

    SpringBoot整合Pulsar的实现示例

    本文主要介绍了SpringBoot整合Pulsar的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • 如何通过XML方式配置并实现Mybatis

    如何通过XML方式配置并实现Mybatis

    这篇文章主要介绍了如何通过XML方式配置并实现Mybatis,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • 在IDEA中搭建最小可用SpringMVC项目(纯Java配置)

    在IDEA中搭建最小可用SpringMVC项目(纯Java配置)

    这篇文章主要介绍了在IDEA中搭建最小可用SpringMVC项目(纯Java配置),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • java实现快速排序的方法

    java实现快速排序的方法

    这篇文章主要介绍了java实现快速排序的方法,涉及java排序的相关操作技巧,需要的朋友可以参考下
    2015-05-05
  • Spring Bean生命周期源码原理图解

    Spring Bean生命周期源码原理图解

    这篇文章主要介绍了Spring Bean生命周期源码原理图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • java安全 ysoserial CommonsCollections1示例解析

    java安全 ysoserial CommonsCollections1示例解析

    这篇文章主要介绍了java安全 ysoserial CommonsCollections1示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • Java编译错误问题:需要class,interface或enum

    Java编译错误问题:需要class,interface或enum

    这篇文章主要介绍了Java编译错误问题:需要class,interface或enum,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-02-02
  • Spring Cache+Redis缓存数据的实现示例

    Spring Cache+Redis缓存数据的实现示例

    本文主要介绍了Spring Cache+Redis缓存数据,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01

最新评论