JAVA 并发编程-读写锁之模拟缓存系统(十一)

在多线程中,为了提高效率有些共享资源允许同时进行多个读的操作,但只允许一个写的操作,比如一个文件,只要其内容不变可以让多个线程同时读,不必做排他的锁定,排他的锁定只有在写的时候需要,以保证别的线程不会看到数据不完整的文件。这时候就需要使用读写锁。

/**
 * 简单读写锁demo
 * @author hejingyuan
 *
 */
public class ReadWriteLockTest {
	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		//创建几个线程
		for(int i=0;i<3;i++)
		{
			new Thread(){
				public void run(){
					while(true){
						q3.get();
					}
				}

			}.start();

			new Thread(){
				public void run(){
					while(true){
						q3.put(new Random().nextInt(10000));
					}
				}			

			}.start();

		}

	}
}

class Queue3{
	private Object data = null;//共享数据,只能有一个线程能写该数据,但可以有多个线程同时读该数据
	//读写锁
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	//读数据
	public void get(){
		rwl.readLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to read data!");
			Thread.sleep((long)(Math.random()*1000));
			System.out.println(Thread.currentThread().getName() + "have read data :" + data);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}
	//写数据
	public void put(Object data){

		rwl.writeLock().lock();
		try {
			System.out.println(Thread.currentThread().getName() + " be ready to write data!");
			Thread.sleep((long)(Math.random()*1000));
			this.data = data;
			System.out.println(Thread.currentThread().getName() + " have write data: " + data);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}

	}
}

运行结果:

Thread-0 be ready to readdata!

Thread-2 be ready to readdata!

Thread-2have read data:null

Thread-0have read data:null

Thread-1 be ready towrite data!

Thread-1 have write data:1021

Thread-1 be ready towrite data!

Thread-1 have write data:2887

看到这里不免有人会问,既然读的时候可以多人访问,那么为什么还要加读锁呢?

答:当然要加锁了,否则在写时去读,可能不正确-(写的时候不能去读)

读写锁-模拟缓存系统实现:

public class CacheDemo {

	private Map<String, Object> cache = new HashMap<String, Object>();
	public static void main(String[] args) {

	}

	//定义读写锁
	private ReadWriteLock rwl = new ReentrantReadWriteLock();
	//读数据,使用读锁
	public  Object getData(String key){
		//添加读锁
		rwl.readLock().lock();
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){
				//释放读锁
				rwl.readLock().unlock();
				//加上写锁
				rwl.writeLock().lock();
				try{
					//假设三个线程同时去获取写锁,我们知道只有第一个线程能够获取
                    //那么其他两个线程只有等了,如果第一个线程按流程执行完后,刚才的两个线程可以得到写锁了,
                    //然后接着就可以修改数据了(赋值).所以加上判断!
					if(value==null){//为什么还要判断?
						value = "aaaa";//实际是去queryDB();
					}
				}finally{
					//释放写锁
					rwl.writeLock().unlock();
				}
				rwl.readLock().lock();
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
}

总结:

读写锁的作用为,当我们加上写锁时,其他线程被阻塞,只有一个写操作在执行,当我们加上读锁后,它是不会限制多个读线程去访问的。也就是get和put之间是互斥的,put与任何线程均为互斥,但是get与get线程间并不是互斥的。其实加读写锁的目的是同一把锁的读锁既可以与写锁互斥,读锁之间还可以共享。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-29 19:06:54

JAVA 并发编程-读写锁之模拟缓存系统(十一)的相关文章

java并发编程-读写锁

最近项目中需要用到读写锁 读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源.但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写,也就是说 读-读能共存,读-写不能共存,写-写不能共存 我们直接使用java的读写锁  ReadWriteLock 如下代码是使用缓存的典型场景: public class ReadW

多线程之使用读写锁ReentrantReadWriteLock实现缓存系统

简单地缓存系统:当有线程来取数据时,如果该数据存在我的内存中,我就返回数据:如果不存在我的缓存系统中,那么就去查数据库,返回数据的同时保存在我的缓存中. 其中涉及到读写问题:当多个线程执行读操作时(都加读锁),如果有数据返回:如果没有数据时,则让第一个读的线程,进行获取数据,然后进行写操作,这时需要第一个线程先释放掉读锁然后加写锁.第一个写完后,在家读锁,其他线程使用时判断,如果存在该数据,在直接过去读取不用加写锁. API上缓存例子如下: class CachedData { Object d

Java并发编程ReentrantReadWriteLock

基于AQS的前世今生,来学习并发工具类ReentrantReadWriteLock.本文将从ReentrantReadWriteLock的产生背景.源码原理解析和应用来学习这个并发工具类. 1. 产生背景 前面我们学习的重入锁ReentrantLock本质上还是互斥锁,每次最多只能有一个线程持有ReentrantLock.对于维护数据完整性来说,互斥通常是一种过于强硬的规则,因此也就不必要的限制了并发性.互斥是一种保守的加锁策略,虽然可以避免"写/写"冲突和"写/读"

读《Java并发编程的艺术》(一)

离开博客园很久了,自从找到工作,到现在基本没有再写过博客了.在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜.所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督促自己要不断的学习,不断的进步. 最近在进一步学习Java并发编程,不言而喻,这部分内容是很重要的.现在就以<并发编程的艺术>一书为主导线,开始新一轮的学习. 进程和线程 进程是一个应用程序在处理机上的一次执行过程,线程是进程的最小基本单位(个人理解).一个进程可以包含多个线程. 上下文切换 我们

基于JVM原理JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的Java开发工作中,仅仅了解并发编程的创建.启动.管理和通信等基本知识还是不够的.一方面,如果要开发出高效.安全的并发程序,就必须深入Java内存模型和Java虚拟机的工作原理,从底层了解并发编程的实质:更进一步地,在现今大数据的时代,要开发出高并发.高可用.考可靠的分布式应用及各种中间件,更需要深

[Java并发编程实战]构建一个高效可复用缓存程序(含代码)

[Java并发编程实战]构建一个高效可复用缓存程序(含代码) 原文地址:https://www.cnblogs.com/chengpeng15/p/9915800.html

读Java并发编程实践中,向已有线程安全类添加功能--客户端加锁实现示例

在Java并发编程实践中4.4中提到向客户端加锁的方法.此为验证示例,写的不好,但可以看出结果来. package com.blackbread.test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public

《Java并发编程实战》要点笔记及java.util.concurrent 的结构介绍

买了<java并发编程实战>这本书,看了好几遍都不是很懂,这个还是要在实战中找取其中的要点的,后面看到一篇文章笔记做的很不错分享给大家!! 原文地址:http://blog.csdn.net/cdl2008sky/article/details/26377433 Subsections  1.线程安全(Thread safety) 2.锁(lock) 3.共享对象 4.对象组合 5.基础构建模块 6.任务执行 7.取消和关闭 8.线程池的使用 9.性能与可伸缩性 10.并发程序的测试 11.显

转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)

简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接口有3个实现它的类:ReentrantLock.ReetrantReadWriteLock.ReadLock和ReetrantReadWriteLock.WriteLock,即重入锁.读锁和写锁.lock必须被显式地创建.锁定和释放,为了可以使用更多的功能,一般用ReentrantLock为其实例化