ReentrantReadWriteLock读写锁

r囧r小猫 2022-12-16 03:58 254阅读 0赞

ReentrantReadWriteLock是一把可重入读写锁,提高了读的性能。读写锁时如何实现了呢。

其实读写锁还是通过一个compareAndSet实现的,只是里面的state的含义不一样了,原先是表示线程的重入次数,现在对该变量做了拆分。高16位表示读线程的重入次数,第16位表示写线程的重入次数。

下面我们看几个变量和方法

  1. static final int SHARED_SHIFT = 16;
  2. //1 0000 0000 0000 0000 用于读线程重入一次
  3. static final int SHARED_UNIT = (1 << SHARED_SHIFT);
  4. //读线程最大重入次数
  5. static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
  6. //FFFF FFFF FFFF FFFF 用于计算写线程重入次数
  7. static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
  8. //获取读线程重入次数
  9. static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
  10. //获取写线程重入次数
  11. static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

获取写锁

  1. final boolean tryWriteLock() {
  2. Thread current = Thread.currentThread();
  3. int c = getState();
  4. //如果c等于0,说明空闲,如果非0,说明已经被占用了
  5. if (c != 0) {
  6. //获取写线程重入次数
  7. int w = exclusiveCount(c);
  8. //如果当前没有写线程,或者写线程不是当前线程,直接返回失败
  9. if (w == 0 || current != getExclusiveOwnerThread())
  10. return false;
  11. //如果写线程已经超过最大重入次数了,则报错
  12. if (w == MAX_COUNT)
  13. throw new Error("Maximum lock count exceeded");
  14. }
  15. //占用锁
  16. if (!compareAndSetState(c, c + 1))
  17. return false;
  18. setExclusiveOwnerThread(current);
  19. return true;
  20. }

获取读锁

  1. final boolean tryReadLock() {
  2. Thread current = Thread.currentThread();
  3. for (;;) {
  4. int c = getState();
  5. //如果当前存在写锁,并且不是当前线程,则直接获取锁失败
  6. if (exclusiveCount(c) != 0 &&
  7. getExclusiveOwnerThread() != current)
  8. return false;
  9. //获取读锁重入次数
  10. int r = sharedCount(c);
  11. if (r == MAX_COUNT)
  12. throw new Error("Maximum lock count exceeded");
  13. //读锁占用
  14. if (compareAndSetState(c, c + SHARED_UNIT)) {
  15. if (r == 0) {
  16. firstReader = current;
  17. firstReaderHoldCount = 1;
  18. } else if (firstReader == current) {
  19. firstReaderHoldCount++;
  20. } else {
  21. HoldCounter rh = cachedHoldCounter;
  22. if (rh == null || rh.tid != getThreadId(current))
  23. cachedHoldCounter = rh = readHolds.get();
  24. else if (rh.count == 0)
  25. readHolds.set(rh);
  26. rh.count++;
  27. }
  28. return true;
  29. }
  30. }
  31. }

发表评论

表情:
评论列表 (有 0 条评论,254人围观)

还没有评论,来说两句吧...

相关阅读

    相关 ReentrantReadWriteLock

    1. 写锁比读锁的优先级要高,拥有写锁之后还可以再获取读锁,但是拥有读锁的线程在释放前无法再获取写锁。 2. 允许锁降级,即从写锁降级为读锁,实现的步骤是:先获取写锁,再获