7、ReadWriteLock

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥,这是由JVM控制的,我们只要上好相应的锁即可。

如果你的代码只读数据,可以很多人同时读,但是不能同时写,那就上读锁;如果代码修改数据,只能一个人在写,且不能同时读取,

那就上写锁。总之,读的时候上读锁,写的时候上写锁。

java.util.concurrent.lock

Interface ReadWriteLock

实现类:

ReentrantReadWriteLock

ReadWriteLock实现了两把锁,一把只能进行读操作,一把进行写操作。读锁能够被多个线程拥有,写锁具有排他性。

所有ReadWriteLock的实现必须保证写锁操作对于读锁操作内存的同步(当然拥有写锁时具有排他性,此时只要保证写操作的内存对读操作

保持可见性就可以了,当然也就是所谓的同步了)。通俗点说,一个成功获得读锁的线程能够看到所有先前释放的写锁的更新。

读写锁比相互排它锁支持更大的并发量。它利用的一个事实是:同一时间只能有一个线程对共享数据进行更新,但是可以有多个线程对它进行读取。

读写锁的实现当然要比互斥锁的实现更难。此时,我们的应用到底是选择互斥锁还是读写锁,取决于我们应用读写操作发生的频率。如果读操作是频繁

发生的,而写操作不那么频繁,那么可以选择读写锁,这样会提高应用的性能;反之,如果我们的应用写操作比较频繁而读操作不那么频繁,并且读操作

是一些短时间的操作,那么就没有必要用到读写锁。

利用ReentrantReadWriteLock实现缓存:

 1 class CachedData {
 2     Object data;
 3     volatile boolean cacheValid;
 4     ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
 5
 6     void processCachedData() {
 7         rwl.readLock().lock();
 8         if(!cacheValid) {
 9             //在获得写锁之前必须释放读锁
10             rwl.readLock().unlock();
11             rwl.writeLock().lock();
12
13             //再次检测状态,因为其他线程有可能获得
14             //写锁并且在我们操作之前改变了状态
15             if(!cacheValid) {
16                 //data=....;
17                 cacheValid=true;
18             }
19             //在释放写锁之前通过获得读锁进行降级
20             rwl.readLock().lock();
21             rwl.writeLock().unlock();//释放写锁仍然拥有读锁
22         }
23         use(data);
24         rwl.readLock().unlock();
25     }
26 }

利用ReentrantReadWriteLock提供集合的并发性能:

 1 class RWDictionary {
 2         private final Map<String,Data> m=new TreeMap<String,Data>();
 3         private final ReentrantReadWriteLock rwl=new ReentrantReadWriteLock();
 4         private final Lock r=rwl.readLock();
 5         private final Lock w=rwl.writeLock();
 6
 7         public Data get(String key) {
 8             r.lock();
 9             try {
10                 return m.get(key);
11             }finally {
12                 r.unlock();
13             }
14         }
15
16         public String[] allKeys() {
17             r.lock();
18             try {
19                 return (String[])m.keySet().toArray();
20             }finally {
21                 r.unlock();
22             }
23         }
24
25         public Data put(String key,Data value) {
26             w.lock();
27             try {
28                 return m.put(key, value);
29             }finally {
30                 w.unlock();
31             }
32         }
33
34         public void clear() {
35             w.lock();
36             try {
37                 m.clear();
38             }finally {
39                 w.unlock();
40             }
41         }
42     }
时间: 2024-10-09 23:33:37

7、ReadWriteLock的相关文章

同步中的四种锁synchronized、ReentrantLock、ReadWriteLock、StampedLock

目录 1.synchronized同步锁 2.ReentrantLock重入锁 3.ReadWriteLock读写锁 4.StampedLock戳锁(目前没找到合适的名字,先这么叫吧...) 5.总结 =======正文分割线========== 为了更好的支持并发程序,JDK内部提供了多种锁.本文总结4种锁. 1.synchronized同步锁 使用: synchronized本质上就2种锁: 1.锁同步代码块 2.锁方法 可用object.wait() object.notify()来操作线

synchronized、Lock、ReentrantLock、ReadWriteLock

synchronized:同步锁,是java内置的关键字.当一个线程A执行到被synchronized修饰的方法时,其他线程B如果也要执行这个方法,那么B只能等A执行完方法释放锁后才能获取资源锁执行synchronized方法块. synchronized释放锁的情况 1,执行完改代码块,释放锁 2,执行时发生异常,jvm自动释放 lock:是一个类,通过这个类可以实现同步访问 lock和synchronized最大不同点.lock释放锁需要手动释放,如果没有手动释放则会导致死锁的现象 而syn

ReadWriteLock与ReentrantReadWriteLock

JAVA的JUC包中的锁包括"独占锁"和"共享锁".JUC中的共享锁有:CountDownLatch.CyclicBarrier.Semaphore.ReentrantReadWriteLock等.本章会以ReentrantReadWriteLock为蓝本对共享锁进行说明. 一.ReentrantLock与ReentrantReadWriteLock 说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限.它和后者都是单独

【java多线程】(3)---synchronized、Lock

synchronized.Lock 一.概述 1.出现线程不安全的原因是什么? 如果我们创建的多个线程,存在着共享数据,那么就有可能出现线程的安全问题:当其中一个线程操作共享数据时,还未操作完成,另外的线程就参与进来,导致对共享数据的操作出现问题. 2.线程不安全解决办法 要求一个线程操作共享数据时,只有当其完成操作完成共享数据,其它线程才有机会执行共享数据.java提供了两种方式来实现同步互斥访问:synchronized和Lock. 二.synchronized synchronized可以

Java多线程-新特征-锁(上)

在Java5中,专门提供了锁对象,利用锁可以方便的实现资源的封锁,用来控制对竞争资源并发访问的控制,这些内容主要集中在java.util.concurrent.locks 包下面,里面有三个重要的接口Condition.Lock.ReadWriteLock. Condition: Condition 将 Object 监视器方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-se

多线程概念

一个进程是由一个或者N个线程组成的! 线程:cpu调度和分配的基本单位!电脑中真正执行的是线程! 在同一个时间点,我们的电脑只能运行一个线程 多线程: 如果在一个进程中,同时运行多个线程,来完成不同的工作,我们称之为多线程! CUP不能同时运行多个线程! 一个CPU在同一个时间点,只能运行一个线程,单线程运行的速度太快,我们肉眼无法分辨,所以我们认为是多线程! 生活中进入地铁站的例子: 场景1:现在地铁站有1个进站口,同时来了5个人! 需要排队进站! 场景2:现在地铁站有5个进站口,同时来了5个

40个多线程问题总结

前言 多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行总结的,因此罗列了40个多线程的问题. 这些多线程的问题,有些来源于各大网站.有些来源于自己的思考.可能有些问题网上有.可能有些问题对应的答案也有.也可能有些各位网友也都看过,但是本文写作的重心就是所有的问题都会按照自己的理解回答一遍,不会去看网上的答案,因此可能有些问题讲的不对,能指正的希望大家不吝指教.

JDK并发工具之多线程团队协作:同步控制

一.synchronized的功能扩展:重入锁(java.util.concurrent.locks.ReentrantLock) 重入锁可以完全替代synchronized关键字.在JDK 5.0的早期版本中,重入锁的性能远远好于synchronized,但从JDK 6.0开始,JDK在syn-chronized上做了大量的优化,使得两者的性能差距并不大. 01 public class ReenterLock implements Runnable{ 02 public static Ree

SYNCHRONIZED和LOCK比较浅析

synchronized是基于jvm底层实现的数据同步,lock是基于Java编写,主要通过硬件依赖CPU指令实现数据同步.下面一一介绍 一.synchronized的实现方案 1.synchronized能够把任何一个非null对象当成锁,实现由两种方式: a.当synchronized作用于非静态方法时,锁住的是当前对象的事例,当synchronized作用于静态方法时,锁住的是class实例,又因为Class的相关数据存储在永久带,因此静态方法锁相当于类的一个全局锁. b.当synchro