zoukankan      html  css  js  c++  java
  • 读写锁的一些错误记忆修正

    1.先以一段代码为例

    ReadWriteLock rwLock = new ReentrantReadWriteLock();
    
    // rwLock.readLock()是获取rwLock里的一个属性而非new
    // 这句代码的意思是给rwLock加读锁,而不应该理解为给rwLock.readLock()的返回值加锁
    // 这点Go比java好,go里读写锁就是提供四个方法,而java里拆成两个属性来提供让人误解
    rwLock.readLock().lock();

    2.读写锁对象里的读锁属性rwLock.readLock()和写锁属性rwLock.writeLock()里加锁或者释放锁都是针对rwLock的而非针对其读锁属性或写锁属性;

    3.之前有个错误的记忆,就是读写锁rwLock如果加了读锁后,加写锁会被阻塞,此时再给rwLock加读锁是不会成功的,这个记忆是错误的;rwLock只要当前状态是已经被加了读锁状态,不管此时是否存在某个线程要给rwLock加写锁(会被阻塞)

    ,再给它加读锁都是成功的;

    4.每次加锁都会保存一个锁数据,这个锁数据里包含了线程信息;java里在A线程里加了某个锁(包括普通锁和读写锁),那么一定要在该线程释放对应的锁(如普通锁,或者读写锁的读锁或写锁);(Go里没有这个要求,在A线程加锁,可以在B线程释放锁,而且Go的锁不是可重入的)

    5.加了多少次锁就要释放多少次锁,比如普通lock在一个代码块里lock了两次,那么就必须unlock两次,否则其他地方仍然是无法获得锁的;这个同样适用于读锁,比如rwLock加了3次读锁,这个时候写锁被阻塞,必须释放三次读锁写锁才会获得加锁的权限;

    6.rwLock加了写锁后,然后存在一个加写锁的被阻塞和加读锁的被阻塞的两个线程,此时释放rwLock的写锁,然后这两个阻塞的线程会公平的去“争抢”rwLock的写锁或读锁(而不是因为之前的是写锁,所以下一个一定是优先写锁或读锁)

    ,经过测试,到底是谁“争抢”成功,主要看这两个线程哪个先运行到rwLock加读/写锁的那句代码,先被阻塞的会先被唤醒去获得锁(当然不同的JVM可能不一样,所以这个不能当定论,只能说我的JVM测试结果是这样);

    7.读写锁在一般用于读次数远远大于写次数的情况,但是如果说长时间都是一直存在读线程加读锁,那么就会造成写饥饿,即写锁线程一直没法加写锁,这个没有好的解决方法,一般就是将锁的fair设置为true,不过这样锁的效率又会降低很多。

  • 相关阅读:
    Scrapy数据持久化
    Mybatis源码与Spring源码中设计模式的应用总结
    Count-Min Sketch 算法
    加解密算法、消息摘要、消息认证技术、数字签名与公钥证书
    智能卡系统设计(一) 断电保护和数据备份
    TCP/IP协议——ARP详解
    DES算法详解
    Python调用外部程序——os.system()和subprocess.call()
    Python实现截图
    Linux笔记:SSH客户端断开配置
  • 原文地址:https://www.cnblogs.com/silentdoer/p/12745548.html
Copyright © 2011-2022 走看看