美文网首页
大话ReentrantLock

大话ReentrantLock

作者: kele2018 | 来源:发表于2024-06-25 17:01 被阅读0次

    晚饭后,老王和媳妇在路上走。
    “听说今天诊所又有人打架了?”老王媳妇突然说。
    “两对年轻的夫妇,都是来给孩子看病的,说实在的,我也的确没有看清楚他们到底谁先来的,但他们都说自己先来的。”老王无奈的说。
    “要是我也能看病就好了,这样他们就不用打架了。”媳妇安慰老王。
    “咱两都看病,谁抓药呢!”老王心中的无奈更重了。
    老王和媳妇的诊所在可乐镇开了二十年了,因为效果好,价格也公道,所以每天慕名前来看病的人不少。
    “你看这样行不行,”两人沉默了一会儿,老王突然说,“我们在门上挂一个牌子,谁先拿到这个牌子,就先给谁看。”
    “但是抢牌子会不会打架?”媳妇问。
    “不会,牌子上会随机附上一道关于健康知识的问题,谁先答上来谁就先拿到牌子。”老王早有准备。
    “会不会同时答上来?”
    “会不会,谁先答上来的,还不是由咱们说了算。”老王有点得意。
    “那没有抢到牌子的怎么办?”
    “我准备重新改造下现在的候诊区,给每个座位编上号,然后按照从小到大的顺序排列,没有抢到牌子的就到最小且空闲的号上等待。新进来的人可以直接排队,也可以不排队,直接去抢牌子。”
    “那他肯定抢不到......”媳妇机智地说。
    “也不一定,假如当他去抢牌子的时候,看完病的人正好出来把牌子复位到了门上......”
    “也对,这个时候就能抢到牌子了。”
    “也不一定,因为看完病的人还会唤醒等待队列最前面的人。”老王给刚才候诊的队列起了个名字叫等待队列。
    “对,这个时候就是两人回答问题竞争了。”媳妇恍然大悟。

    代码实现故事
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    } // 公平锁:进来后,直接去排队   非公平锁:进来后,先抢一次牌子,再去排队
    final void lock() {
        if (compareAndSetState(0, 1)){
            setExclusiveOwnerThread(Thread.currentThread());
        }  // 先抢一次牌子    
        else{
            acquire(1);
        }          
    }
    public final void acquire(int arg) {
        if (!tryAcquire(arg) // 没有抢到牌子
            &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg)){ // 排队
            selfInterrupt();
        }   
    }
    /**
    排队逻辑:
    1、0号椅子不坐人,队列的头和尾都指向0号椅子
    2、第一个人坐1号椅子,队列的头指向0号椅子,队列的尾指向1号椅子
    3、第二个人坐2号椅子,队列的头指向0号椅子,队列的尾指向2号椅子
    4、以此类推
    **/
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        Node pred = tail; 
        if (pred != null) {
          node.prev = pred;
          if (compareAndSetTail(pred, node)) { 
            pred.next = node;
            return node;
          }
        }
        enq(node);
        return node;
     }
     private Node enq(final Node node) {
        for (; ; ) {
          Node t = tail;
          if (t == null) { 
            if (compareAndSetHead(new Node()))
            tail = head;
          } else {
            node.prev = t;
            if (compareAndSetTail(t, node)) {
              t.next = node;
              return t;
            }
          }
        }
     }
    
    

    “如果抢到牌子的人进来后,却发现自己没有带医保卡,怎么办?”媳妇突然问。
    “候诊室内,我开辟了几块空间,每块空间的椅子也编上号,然后按照从小到大的顺序排列,没有带医保卡的在一块空间排队,没有带身份证的在一块空间排队,总之一类人一个队伍。”老王说。
    “那我们现在的地方岂不是不够用了。”媳妇担忧的说。
    “按照我的想法,条件队列没有数量限制,”老王给刚才的空间起了个名字,“不过一般情况也不会有那么多人去排队,所以我们先紧着目前的地方用,不够用了再说。”老王自行的说。
    “那他们就一直在那里排队,医保卡也不会自己飞过来找他们啊!”媳妇又提出一个担忧。
    “那是自然的,他们得通知家里人,把医保卡送过来,然后唤醒他到等待队列中继续去排队。”老王解释到。

    相关文章

      网友评论

          本文标题:大话ReentrantLock

          本文链接:https://www.haomeiwen.com/subject/tncjcjtx.html