jdk 源码分析(7)java ReentrantLock结构

来源:互联网 发布:go语言编程 pdf 编辑:程序博客网 时间:2024/06/05 20:11
lock看上去很牛,其实真的很牛,如果你仔细研究代码发现,所以的lock都只是去争一个变量state
private volatile int state;
如果你能将这个state从零变成1,你就可以获得资源,

因为要判断是谁获得了这个state,所以需要保留这个线程的对象。
因为要记录有哪些线程在争论lock,所以需要队列,既然有队列,就有队列的机制,公平机制(先到先得),非公平机制(可能存在饿死的线程,一直得不到)。这里的队列是用Node组成的链表,记录了head和tail。

源码:
public ReentrantLock() {    sync = new NonfairSync();}
默认采用非公平的机制。

对比公平和非公平:
非公平的lock 直接先去尝试获取一次线程,如果拿不到再去排队。
  1. final void lock() {
  2.             //这里就是上面说的争的对象。
  3. if (compareAndSetState(0, 1))
  4. setExclusiveOwnerThread(Thread.currentThread());
  5. else
  6. acquire(1);
  7. }
公平的,会直接去排队。
  1. final void lock() {
  2. acquire(1);
  3. }
公平的申请:
  1. protected final boolean tryAcquire(int acquires) {
  2. final Thread current = Thread.currentThread();
  3. int c = getState();
  4.             //没人用:
  5. if (c == 0) {
  6.                 //但是还要问问是否有人在我前面排队
  7. if (!hasQueuedPredecessors() &&
  8. compareAndSetState(0, acquires)) {
  9. setExclusiveOwnerThread(current);
  10. return true;
  11. }
  12. }
  13.             //如果是本线程占用用还是会让过去的。一家人不做两家事
  14. else if (current == getExclusiveOwnerThread()) {
  15. int nextc = c + acquires;
  16. if (nextc < 0)
  17. throw new Error("Maximum lock count exceeded");
  18. setState(nextc);
  19. return true;
  20. }
  21. return false;
  22. }

对比非公平的就直接了当得多,从不在乎别人的感受
  1. final boolean nonfairTryAcquire(int acquires) {
  2. final Thread current = Thread.currentThread();
  3. int c = getState();
  4.     //没人用
  5. if (c == 0) {
  6.             //那我用吧
  7. if (compareAndSetState(0, acquires)) {
  8. setExclusiveOwnerThread(current);
  9. return true;
  10. }
  11. }
  12.             //一家人
  13. else if (current == getExclusiveOwnerThread()) {
  14. int nextc = c + acquires;
  15. if (nextc < 0) // overflow
  16. throw new Error("Maximum lock count exceeded");
  17. setState(nextc);
  18. return true;
  19. }
  20. return false;
  21. }

世事可能不如意,所以需要排队。在末尾添加。
  1. private Node addWaiter(Node mode) {
  2. Node node = new Node(Thread.currentThread(), mode);
  3. // Try the fast path of enq; backup to full enq on failure
  4. Node pred = tail;
  5. if (pred != null) {
  6. node.prev = pred;
  7. if (compareAndSetTail(pred, node)) {
  8. pred.next = node;
  9. return node;
  10. }
  11. }
  12. enq(node);
  13. return node;
  14. }


排队的用户怎么执行能,肯定在循环中,

  1. final boolean acquireQueued(final Node node, int arg) {
  2. boolean failed = true;
  3. try {
  4. boolean interrupted = false;
  5. for (;;) {
  6. final Node p = node.predecessor();
  7. if (p == head && tryAcquire(arg)) {
  8. setHead(node);
  9. p.next = null; // help GC
  10. failed = false;
  11. return interrupted;
  12. }
  13. if (shouldParkAfterFailedAcquire(p, node) &&
  14. parkAndCheckInterrupt())
  15. interrupted = true;
  16. }
  17. } finally {
  18. if (failed)
  19. cancelAcquire(node);
  20. }
  21. }

到此结束。

问题:每个Node都有一个State吗?还是共用的呢。

原创粉丝点击