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

ReadWriteMap.java

  1. public class ReadWriteMap<K, V> {
  2. private final Map<K, V> map;
  3. private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  4. private final Lock readLock = readWriteLock.readLock();
  5. private final Lock writeLock = readWriteLock.writeLock();
  6.  
  7. public ReadWriteMap(Map<K, V> map){
  8. this.map = map;
  9. }
  10.  
  11. public V put(K key, V value){
  12. writeLock.lock();
  13. try{
  14. return map.put(key, value);
  15. } finally {
  16. //释放锁,一定要写在finally里面
  17. writeLock.unlock();
  18. }
  19. }
  20.  
  21. public V get(K key){
  22. readLock.lock();
  23. try{
  24. return map.get(key);
  25. } finally {
  26. readLock.unlock();
  27. }
  28. }
  29.  
  30. }

ConcurrentHashMap里面的putVal()方法

  1. /** Implementation for put and putIfAbsent */
  2. final V putVal(K key, V value, boolean onlyIfAbsent) {
  3. if (key == null || value == null) throw new NullPointerException();
  4. int hash = spread(key.hashCode());
  5. int binCount = 0;
  6. for (Node<K,V>[] tab = table;;) {
  7. Node<K,V> f; int n, i, fh;
  8. if (tab == null || (n = tab.length) == 0)
  9. tab = initTable();
  10. else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
  11. if (casTabAt(tab, i, null,
  12. new Node<K,V>(hash, key, value, null)))
  13. break; // no lock when adding to empty bin
  14. }
  15. else if ((fh = f.hash) == MOVED)
  16. tab = helpTransfer(tab, f);
  17. else {
  18. V oldVal = null;
  19. synchronized (f) {
  20. if (tabAt(tab, i) == f) {
  21. if (fh >= 0) {
  22. binCount = 1;
  23. for (Node<K,V> e = f;; ++binCount) {
  24. K ek;
  25. if (e.hash == hash &&
  26. ((ek = e.key) == key ||
  27. (ek != null && key.equals(ek)))) {
  28. oldVal = e.val;
  29. if (!onlyIfAbsent)
  30. e.val = value;
  31. break;
  32. }
  33. Node<K,V> pred = e;
  34. if ((e = e.next) == null) {
  35. pred.next = new Node<K,V>(hash, key,
  36. value, null);
  37. break;
  38. }
  39. }
  40. }
  41. else if (f instanceof TreeBin) {
  42. Node<K,V> p;
  43. binCount = 2;
  44. if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
  45. value)) != null) {
  46. oldVal = p.val;
  47. if (!onlyIfAbsent)
  48. p.val = value;
  49. }
  50. }
  51. }
  52. }
  53. if (binCount != 0) {
  54. if (binCount >= TREEIFY_THRESHOLD)
  55. treeifyBin(tab, i);
  56. if (oldVal != null)
  57. return oldVal;
  58. break;
  59. }
  60. }
  61. }
  62. addCount(1L, binCount);
  63. return null;
  64. }

使用的是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. bzoj2395 [Balkan 2011]Timeismoney(最小乘积生成树+计算几何)

    题意 每条边有两个权值\(c,t\),请求出一颗生成树,使得\(\sum c\times \sum t\)最小 题解 为什么生成树会和计算几何扯上关系-- 对于每棵树,设\(x=c,y=t\),我们可 ...

  2. Mysql数据库申请

    前段时间大部门下新成立了一个推广百度OCR.文字识别.图像识别等科技能力在金融领域应用的子部门.因为部门刚成立,基础设施和人力都是欠缺的.当时分到我们部门的任务是抽调一个人做新部门主站前端开发工作.本 ...

  3. 第9项:尽量使用try-with-resources而不是try-finally(Prefer try-with-resources to try-finally)

      Java库包含许多必须通过调用close方法手动关闭的资源. 示例包括InputStream,OutputStream和java.sql.Connection. 关闭资源经常被客户忽视,可预见的可 ...

  4. 5. pytest的断言

    一.pytest 支持Python自带的标准断言 def f(): return 3 def test_function(): assert f() == 4 pytest 的断言报告,也很丰富,和详 ...

  5. 7、C++枚举类型

    7.枚举类型 C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const.它还允许定义新类型,但必须按严格的限制进行.使用enum的语法与使用结构的相似. enum spectru ...

  6. js 的常用选择器

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

  7. Android GPS应用(获取定位信息)

    1.介绍 2.使用方法 3.在AndroidManifest.xml文件中添加 <uses-permission android:name="android.permission.AC ...

  8. xml转换csv

    /// <summary> /// xml文件转换为CSV /// </summary> /// <param name="fileName"> ...

  9. 在URL地址栏中显示ico

             <!-- 在URL地址栏中显示ico -->         <link Rel="SHORTCUT ICON" href="imag ...

  10. 【KMP】洛谷P2375 [NOI2014]动物园 题解

        一开始的方向应该对了,但是没有想到合理的优化还是没写出来…… 题目描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己 ...