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

  1. /**
  2. * 简单读写锁demo
  3. * @author hejingyuan
  4. *
  5. */
  6. public class ReadWriteLockTest {
  7. public static void main(String[] args) {
  8. final Queue3 q3 = new Queue3();
  9. //创建几个线程
  10. for(int i=0;i<3;i++)
  11. {
  12. new Thread(){
  13. public void run(){
  14. while(true){
  15. q3.get();
  16. }
  17. }
  18.  
  19. }.start();
  20.  
  21. new Thread(){
  22. public void run(){
  23. while(true){
  24. q3.put(new Random().nextInt(10000));
  25. }
  26. }
  27.  
  28. }.start();
  29.  
  30. }
  31.  
  32. }
  33. }
  34.  
  35. class Queue3{
  36. private Object data = null;//共享数据。仅仅能有一个线程能写该数据,但能够有多个线程同一时候读该数据
  37. //读写锁
  38. ReadWriteLock rwl = new ReentrantReadWriteLock();
  39. //读数据
  40. public void get(){
  41. rwl.readLock().lock();
  42. try {
  43. System.out.println(Thread.currentThread().getName() + " be ready to read data!");
  44. Thread.sleep((long)(Math.random()*1000));
  45. System.out.println(Thread.currentThread().getName() + "have read data :" + data);
  46. } catch (InterruptedException e) {
  47. e.printStackTrace();
  48. }finally{
  49. rwl.readLock().unlock();
  50. }
  51. }
  52. //写数据
  53. public void put(Object data){
  54.  
  55. rwl.writeLock().lock();
  56. try {
  57. System.out.println(Thread.currentThread().getName() + " be ready to write data!");
  58. Thread.sleep((long)(Math.random()*1000));
  59. this.data = data;
  60. System.out.println(Thread.currentThread().getName() + " have write data: " + data);
  61. } catch (InterruptedException e) {
  62. e.printStackTrace();
  63. }finally{
  64. rwl.writeLock().unlock();
  65. }
  66.  
  67. }
  68. }

运行结果:

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

看到这里不免有人会问。既然读的时候能够多人訪问。那么为什么还要加读锁呢?

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

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

  1. public class CacheDemo {
  2.  
  3. private Map<String, Object> cache = new HashMap<String, Object>();
  4. public static void main(String[] args) {
  5.  
  6. }
  7.  
  8. //定义读写锁
  9. private ReadWriteLock rwl = new ReentrantReadWriteLock();
  10. //读数据。使用读锁
  11. public Object getData(String key){
  12. //加入读锁
  13. rwl.readLock().lock();
  14. Object value = null;
  15. try{
  16. value = cache.get(key);
  17. if(value == null){
  18. //释放读锁
  19. rwl.readLock().unlock();
  20. //加上写锁
  21. rwl.writeLock().lock();
  22. try{
  23. //如果三个线程同一时候去获取写锁,我们知道仅仅有第一个线程能够获取
  24. //那么其它两个线程仅仅有等了,如果第一个线程按流程运行完后,刚才的两个线程能够得到写锁了,
  25. //然后接着就能够改动数据了(赋值).所以加上推断!
  26. if(value==null){//为什么还要推断?
  27. value = "aaaa";//实际是去queryDB();
  28. }
  29. }finally{
  30. //释放写锁
  31. rwl.writeLock().unlock();
  32. }
  33. rwl.readLock().lock();
  34. }
  35. }finally{
  36. rwl.readLock().unlock();
  37. }
  38. return value;
  39. }
  40. }

总结:

读写锁的作用为,当我们加上写锁时,其它线程被堵塞,仅仅有一个写操作在运行,当我们加上读锁后,它是不会限制多个读线程去訪问的。也就是get和put之间是相互排斥的。put与不论什么线程均为相互排斥。可是get与get线程间并非相互排斥的。事实上加读写锁的目的是同一把锁的读锁既能够与写锁相互排斥,读锁之间还能够共享。

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

  1. java并发编程-读写锁

    最近项目中需要用到读写锁 读写锁适用于读操作多,写操作少的场景,假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁.在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以 ...

  2. java并发:读写锁ReadWriteLock

    在没有写操作的时候,两个线程同时读一个资源没有任何问题,允许多个线程同时读取共享资源. 但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写. 简单来说,多个线程同时操作同一资 ...

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

    简单地缓存系统:当有线程来取数据时.假设该数据存在我的内存中.我就返回数据.假设不存在我的缓存系统中,那么就去查数据库.返回数据的同一时候保存在我的缓存中. 当中涉及到读写问题:当多个线程运行读操作时 ...

  4. Python并发编程-Memcached (分布式内存对象缓存系统)

    一.Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的 ...

  5. Java并发编程实战3-可见性与volatile关键字

    1. 缓存一致性问题 在计算机中,每条指令都是在CPU执行的,而CPU又不具备存储数据的功能,因此数据都是存储在主存(即内存)和外存(硬盘)中.但是,主存中数据的存取速度高于外存中数据的存取速度(这也 ...

  6. java并发编程-StampedLock高性能读写锁

    目录 一.读写锁 二.悲观读锁 三.乐观读 欢迎关注我的博客,更多精品知识合集 一.读写锁 在我的<java并发编程>上一篇文章中为大家介绍了<ReentrantLock读写锁> ...

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

    离开博客园很久了,自从找到工作,到现在基本没有再写过博客了.在大学培养起来的写博客的习惯在慢慢的消失殆尽,感觉汗颜.所以现在要开始重新培养起这个习惯,定期写博客不仅是对自己学习知识的一种沉淀,更是在督 ...

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

    许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存.CPU.缓存等予以说明.实际上,在实际的 ...

  9. 【Java并发编程】从CPU缓存模型到JMM来理解volatile关键字

    目录 并发编程三大特性 原子性 可见性 有序性 CPU缓存模型是什么 高速缓存为何出现? 缓存一致性问题 如何解决缓存不一致 JMM内存模型是什么 JMM的规定 Java对三大特性的保证 原子性 可见 ...

随机推荐

  1. Python机器学习——Agglomerative层次聚类

    层次聚类(hierarchical clustering)可在不同层次上对数据集进行划分,形成树状的聚类结构.AggregativeClustering是一种常用的层次聚类算法.   其原理是:最初将 ...

  2. 获取本地验证码cookie

    window.document.onkeydown = function (evt) { evt = (evt) ? evt : window.event; if (evt.keyCode) { if ...

  3. H5实现调用本地摄像头实现实时视频以及拍照功能

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  4. 用PHP的GD库画五星红旗来玩玩

    1 header("Content-Type:image/jpeg"); $img=imagecreatetruecolor(999,667); $color=imagecolor ...

  5. 4.model 字段

    一.字段名 字段名 类型 参数 AutoField(Field) - int自增列, 必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自 ...

  6. Buffer.alloc()

    Buffer.alloc(size[, fill[, encoding]]) Node.js FS模块方法速查 size {Number} fill {Value} 默认:undefined enco ...

  7. 51NOD 2370 奈芙莲的护符

    >>这是原题传送门<< 答案参考来自 http://www.cnblogs.com/sugewud/p/9822933.html 思路:看到取值范围之后,仅有的思路还是暴力

  8. hadoop_exporter+prometheus

    1.准备工作 安装go.glibe(需要连google服务器,咋连的,我就不写了,因为尝试了各种办法,都失败了,很伤心) 2.下载hadoop_exporter cd /usr/local/prom/ ...

  9. 快捷搜索框(UISearchBar)简单实现 swift

    1.在故事板里面拖入一个搜索栏和一个的tableView.2.创建的ViewController,实现代理:UISearchBarDelegate,UITableViewDataSource,的UIT ...

  10. 贪心算法求解活动安排<算法分析>

    一.实验内容及要求 1.要求按贪心算法原理求解问题: 2.要求手工输入s[10]及f[10],其中注意自己判断s[i]<f[i]: 3.要求显示所有活动及最优活动安排的i事件列表.二.实验步骤  ...