Java读写锁,ReadWriteLock.java接口, RentrantReadWriteLock.java实现。通过读写锁,可以实现读-读线程并发,读-写,写-读线程互斥进行。以前面试遇到一个问题,ConcurrentHashMap的实现原理,如何封装Map效率更高。今天看了《Java并发编程实战》,封装的ReadWriteMap类,效率就比ConcurrentHashMap效率更高,在读多写少的场景。

ReadWriteMap.java

 public class ReadWriteMap<K, V> {
private final Map<K, V> map;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock(); public ReadWriteMap(Map<K, V> map){
this.map = map;
} public V put(K key, V value){
writeLock.lock();
try{
return map.put(key, value);
} finally {
//释放锁,一定要写在finally里面
writeLock.unlock();
}
} public V get(K key){
readLock.lock();
try{
return map.get(key);
} finally {
readLock.unlock();
}
} }

ConcurrentHashMap里面的putVal()方法

  /** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
if (tabAt(tab, i) == f) {
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) {
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}
}
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
if (oldVal != null)
return oldVal;
break;
}
}
}
addCount(1L, binCount);
return null;
}

使用的是synchronized进行同步,synchronized是独占锁,在读多写少的情况下效率不高,极端情况就是所有都是读线程,串行执行。

Java读写锁的更多相关文章

  1. Java并发指南10:Java 读写锁 ReentrantReadWriteLock 源码分析

    Java 读写锁 ReentrantReadWriteLock 源码分析 转自:https://www.javadoop.com/post/reentrant-read-write-lock#toc5 ...

  2. java 读写锁

    http://tutorials.jenkov.com/java-concurrency/read-write-locks.html 翻译 读写锁比LOCK的实现更复杂,想象有一个应用程序能读和写一些 ...

  3. java 读写锁详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt124 在java多线程中,为了提高效率有些共享资源允许同时进行多个读的操作, ...

  4. java读写锁ReadWriteLock

    package com.java.concurrent; import java.util.concurrent.locks.ReadWriteLock; import java.util.concu ...

  5. [图解Java]读写锁ReentrantReadWriteLock

    图解ReentrantReadWriteLock 如果之前使用过读写锁, 那么可以直接看本篇文章. 如果之前未使用过, 那么请配合我的另一篇文章一起看:[源码分析]读写锁ReentrantReadWr ...

  6. Java 读写锁的实现

    一.    synchronized和ReentrantLock的对比 到现在,看到多线程中,锁定的方式有2种:synchronized和ReentrantLock.两种锁定方式各有优劣,下面简单对比 ...

  7. java读写锁实现数据同步访问

    锁机制最大的改进之一就是ReadWriteLock接口和它的唯一实现类ReentrantReadWriteLock.这个类有两个锁,一个是读操作锁,另一个是写操作锁.使用读操作锁时可以允许多个线程同时 ...

  8. Java读写锁(ReentrantReadWriteLock)学习

    什么是读写锁 平时,我们常见的synchronized和Reentrantlock基本上都是排他锁,这些锁在同一时刻只允许一个线程进行访问,哪怕是读操作.而读写锁是维护了一对锁(一个读锁和一个写锁), ...

  9. 轻松掌握java读写锁(ReentrantReadWriteLock)的实现原理

    转载:https://blog.csdn.net/yanyan19880509/article/details/52435135 前言 前面介绍了java中排它锁,共享锁的底层实现机制,本篇再进一步, ...

随机推荐

  1. redis源码分析(3)sds

    sds是redis中用来处理字符串的数据结构.sds的定义在sds.h中: typedef char *sds; 简洁明了!简明扼要!(X,玩我呢是吧!这特么不就是c中的字符串么?!).像redis这 ...

  2. [Swift]八大排序算法(六):希尔排序

    排序分为内部排序和外部排序. 内部排序:是指待排序列完全存放在内存中所进行的排序过程,适合不太大的元素序列. 外部排序:指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存 ...

  3. spring+hibernate中的事务

    上下文: 从数据库服务器上获取数据可以,保存的时候增加了事务提交,即em.flush方法,报错no transaction in progress 报错信息: no transaction in pr ...

  4. 条目四《用empty来代替检查size()是否为0》

    条目四<用empty来代替检查size()是否为0> 首先先说结论: empty()实现为内联函数.(众所周知, 优秀的内联函数的效率比一般函数是高的) 在stl标准库中,empty()对 ...

  5. C#基于SQLiteHelper类似SqlHelper类实现存取Sqlite数据库的方法

    本文实例讲述了C#基于SQLiteHelper类似SqlHelper类实现存取Sqlite数据库的方法.分享给大家供大家参考.具体如下: 这个类不是我实现的,英文原文地址为http://www.egg ...

  6. adminlte+layui框架搭建3 - layui弹出层

    在amdinlte首页引入layui.js 和layui.css后添加代码 <script> layui.use(['layer'], function () { var layer = ...

  7. 1076 Wifi密码 (15 分)

    // 思路是网上以一位大神的,特简单直接采用字符串,判断长度,还有最后一个元素是否T,便可通过ASCll输出数字:#include <iostream> #include <stri ...

  8. LeetCode119.杨辉三角 II

    119.杨辉三角 II 描述 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例 输入: 3 输出: [1,3,3,1] 进阶 ...

  9. docker 使用save和load命令来转移image

    ——假设一个image叫ubuntu—— 在本机执行sudo docker save -o ubuntu.tar ubuntu 由此得到了 ubuntu.tar 文件,将其拷贝到远程机器,执行 sud ...

  10. Fliptile (dfs+二进制压缩)

    Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He ha ...