读写锁:多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。即:读的时候不允许写,写的时候不允许读,可以同时读。
     synchronized关键字和普通的Lock构造的锁,会造成读与读之间的互斥,因此读写锁可提高性能。
 
例子1:三个线程同时对一个共享数据进行读写。
 
 import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockTest {
public static void main(String[] args) {
final Queue queue = new Queue();
for (int i = 0; i < 3; i++) {
new Thread() {
public void run() {
while (true) {
queue.get();
}
} }.start(); new Thread() {
public void run() {
while (true) {
queue.put( new Random().nextInt(10000));
}
} }.start();
} }
} class Queue {
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();
} }
}
例子2:缓存实例
 import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; public class CacheDemo { private static Map<String, Object> cache = new HashMap<String, Object>(); 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 {
// 再次判断该值是否为空,因为如果两个写线程都阻塞在这里,
// 当一个线程被唤醒后value的值为null则进行数据加载,当另外一个线程也被唤醒如果不判断就会执行两次写
if (value == null) {
value = "" ; // query 数据库
cache.put(key, value);
}
} finally {
rwl.writeLock().unlock(); // 释放写锁
}
rwl.readLock().lock(); // 写完之后降级为读锁
}
} finally {
rwl.readLock().unlock(); // 释放读锁
} return value;
} }

读写锁ReadWriteLock和缓存实例的更多相关文章

  1. 线程中的读写锁ReadWriteLock

    Lock锁还有两个非常强大的类 ReadWriteLock接口实现类ReentrantReadWriteLock(非常重要的锁) 想实现 读取的时候允许多线程并发访问,写入的时候不允许. 这种效果.. ...

  2. 显式锁(三)读写锁ReadWriteLock

    前言:   上一篇文章,已经很详细地介绍了 显式锁Lock 以及 其常用的实现方式- - ReetrantLock(重入锁),本文将介绍另一种显式锁 - - 读写锁ReadWriteLock.    ...

  3. 多线程编程_读写锁ReadWriteLock

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 读写锁:分为读 ...

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

    在多线程中,为了提高效率有些共享资源同意同一时候进行多个读的操作,但仅仅同意一个写的操作,比方一个文件,仅仅要其内容不变能够让多个线程同一时候读,不必做排他的锁定,排他的锁定仅仅有在写的时候须要,以保 ...

  5. 【漫画】互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock

    ReentrantLock完美实现了互斥,完美解决了并发问题.但是却意外发现它对于读多写少的场景效率实在不行.此时ReentrantReadWriteLock来救场了!一种适用于读多写少场景的锁,可以 ...

  6. 【漫画】读写锁ReadWriteLock还是不够快?再试试StampedLock!

    本文来源于公众号[胖滚猪学编程] 转载请注明出处! 在互斥锁ReentrantLock不好用?试试读写锁ReadWriteLock一文中,我们对比了互斥锁ReentrantLock和读写锁ReadWr ...

  7. 读-写锁 ReadWriteLock & 线程八锁

    读-写锁 ReadWriteLock: ①ReadWriteLock 维护了一对相关的锁,一个用于只读操作, 另一个用于写入操作. 只要没有 writer,读取锁可以由 多个 reader 线程同时保 ...

  8. Java 读写锁 ReadWriteLock 原理与应用场景详解

    Java并发编程提供了读写锁,主要用于读多写少的场景,今天我就重点来讲解读写锁的底层实现原理@mikechen 什么是读写锁? 读写锁并不是JAVA所特有的读写锁(Readers-Writer Loc ...

  9. C# 多线程编程之锁的使用【互斥锁(lock)和读写锁(ReadWriteLock)】

    多线程编程之锁的使用[互斥锁(lock)和读写锁(ReadWriteLock)] http://blog.csdn.net/sqqyq/article/details/18651335 多线程程序写日 ...

随机推荐

  1. 树莓PI上跑爬虫

    主要是进行主机上使用myeclipse开发后,在从机上跑最后的程序 在主机上和树莓上都安装好java环境,maven,ant 拷到RPI上的时候修改

  2. extern "C"的用法解析(转)

    原文链接:http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html   1.引言 C++语言的创建初衷是“a better C ...

  3. uvalive 3135 Argus priority_queue

    用优先队列维护每个时间点优先级最高的元素. #include<iostream> #include<cstdio> #include<cstdlib> #inclu ...

  4. Java自定义日志输出文件

    Java自定义日志输出文件 日志的打印,在程序中是必不可少的,如果需要将不同的日志打印到不同的地方,则需要定义不同的Appender,然后定义每一个Appender的日志级别.打印形式和日志的输出路径 ...

  5. POJ2389: 大数字乘法算法

    2014-12-26 大数字乘法算法一般是采用模拟"小学生乘法演算过程”方法. 主要算法思想: 1. 乘数a第i)位与乘数b第j)位数字相乘,并将该乘积结果放到乘积结果数组product的第 ...

  6. BNUOJ-29364 Bread Sorting 水题

    题目链接:http://www.bnuoj.com/bnuoj/problem_show.php?pid=29364 题意:给一个序列,输出序列中,二进制1的个数最少的数.. 随便搞搞就行了,关于更多 ...

  7. Java中HashMap和TreeMap的区别深入理解

    首先介绍一下什么是Map.在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value.这就是我们平时说的键值对. Has ...

  8. hdoj 1213 How Many Tables

    How Many Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  9. Servlet+Tomcat 界面登录

    1.文件夹建立(必须按照这个规范,文件名和文件夹名必须一致) a.在%TOMCAT_HOME%\webapps下建立一个文件夹,取名MyWebsit b.在MyWebsit文件夹下新建WEB_INF文 ...

  10. 高效使用Bitmaps(三) 神奇的Cache

    转载:http://my.oschina.net/rengwuxian/blog/184650 应用的场景 假设你开发了一个聊天程序,它的好友列表中显示从网络获取的好友头像.可是如果用户发现每次进入好 ...