• 读写锁ReentrantReadWriteLock


    ReentrantLock无论是“写/写”线程、“读/读”线程、“读/写”线程之间的工作都是互斥,同一 时间只有一个线程能进入同步区域。然而大多实际场景是“读/读”线程间并不存在互斥关系,只有"读/写"线程或"写/写"线程间的操作需要互斥的。

    ReentrantReadWriteLock特性:

     一个资源可以被多个读操作同时访问,而只能对一个写操作访问,但读和写两者不能同时进行。

    从而提高读操作的吞吐量。

    使用场景:对于读多写少的场景使用ReentrantReadWriteLock 性能会比ReentrantLock高出不少。

    在多线程读时互不影响,不像ReentrantLock即使是多线程读也需要每个线程获取锁。不过任何一个线程在写的时候就和ReentrantLock类似,其他线程无论读还是写都必须获取锁。

    需要注意的是同一个线程可以拥有 writeLock readLock (但必须先获取 writeLock 再获取 readLock, 反过来进行获取会导致死锁)

    默认构造方法为 非公平模式 ,开发者也可以通过指定构造方法传参数true设置为 公平模式。

    读锁的条件直接调用ReentrantReadWriteLock的 newCondition 会直接exception public Condition newCondition() {

    throw new UnsupportedOperationException();

    }

     

    1. package com.lock;
    2. import org.apache.log4j.Logger;
    3. import java.util.concurrent.TimeUnit;
    4. import java.util.concurrent.locks.Lock;
    5. import java.util.concurrent.locks.ReentrantReadWriteLock;
    6. /**
    7. * 读写锁
    8. */
    9. public class LockTest6 {
    10. static Logger log = Logger.getLogger(LockTest6.class);
    11. static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    12. //读锁
    13. static Lock r = rwl.readLock();
    14. //写锁
    15. static Lock w = rwl.writeLock();
    16. public static void main(String[] args) throws InterruptedException {
    17. //读
    18. new Thread("读线程1 "){
    19. public void run(){
    20. log.debug("read1 获取 锁");
    21. r.lock();
    22. try {
    23. for (int i = 0; i < 10; i++) {
    24. m1(i);
    25. }
    26. }finally {
    27. r.unlock();
    28. }
    29. }
    30. }.start();
    31. //写
    32. new Thread("写线程--"){
    33. public void run(){
    34. log.debug("write 获取 锁");
    35. w.lock();
    36. try {
    37. for (int i = 0; i < 20; i++) {
    38. m1(i);
    39. }
    40. }finally {
    41. w.unlock();
    42. }
    43. }
    44. }.start();
    45. //读
    46. new Thread("读线程2"){
    47. public void run(){
    48. log.debug("read2 获取 锁");
    49. r.lock();
    50. try {
    51. for (int i = 0; i < 20; i++) {
    52. m1(i);
    53. }
    54. }finally {
    55. r.unlock();
    56. }
    57. }
    58. }.start();
    59. }
    60. public static void m1(int i){
    61. log.debug(Thread.currentThread().getName()+"执行任务 "+i);
    62. try {
    63. TimeUnit.SECONDS.sleep(1);
    64. } catch (InterruptedException e) {
    65. e.printStackTrace();
    66. }
    67. }
    68. }

    1:两个读线程可以并发访问,而写线程只能独自访问(独占)

    2:读写支持重入但是只支持降级不止升级

     

  • 相关阅读:
    前端学习之HTML 下拉框 文本框
    常见问题解答:同时运行 ELEMENTOR FREE 和 ELEMENTOR PRO 插件
    Proteus仿真--从左往右流水灯仿真(仿真文件+程序)
    Pipeline流水线设计的最佳实践
    Python 几行代码实现一键抠图,收费应用 BYEBYE
    sqlserver数据库创建自定义数据类型的表
    鸿蒙布局List简介
    【机器学习】准确率、精确率、召回率、误报率、漏报率概念及公式
    如何简单理解大数据
    hadoop
  • 原文地址:https://blog.csdn.net/asmall_cat/article/details/125549814