首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LockSupport.java中的先进先出互斥锁代码片段

LockSupport.java中的先进先出互斥锁代码片段
EN

Stack Overflow用户
提问于 2020-06-16 04:36:28
回答 2查看 140关注 0票数 1

我正在尝试理解LockSupport.java,并参考了它的文档。在那里,它有代码片段,其中作者提供了使用LockSupport#park()和LockSupport#Unpark()实现互斥的示例。

我使用了该示例,并创建了一个使用该示例FIFOMutex的程序。

FIFOMutex代码(摘自LockSupport.java)

代码语言:javascript
复制
package com.example.java.locking.studies.locksupport.from.javadoc;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

class FIFOMutex {
    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();

    public void lock() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);

        // Block while not first in queue or cannot acquire lock
        while (waiters.peek() != current ||
                !locked.compareAndSet(false, true)) {
            LockSupport.park(this);
            if (Thread.interrupted()) // ignore interrupts while waiting
                wasInterrupted = true;
        }

        waiters.remove();
        if (wasInterrupted) // reassert interrupt status on exit
            current.interrupt();
    }

    public void unlock() {
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }
}

现在,我编写了下面的程序来使用FIFOMutex作为锁定机制,代码如下:

代码语言:javascript
复制
package com.example.java.locking.studies.locksupport.from.javadoc;

public class FIFOMutexMainApp {

    public static void main(String[] args) throws InterruptedException {

        FIFOMutex mutex = new FIFOMutex();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");
                mutex.lock();
                System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");

                for (;;) {

                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Inside thread -> " + Thread.currentThread() + "Before mutex.lock()");

                mutex.unlock();
                System.out.println("Inside thread -> " + Thread.currentThread() + "After mutex.lock()");

                for (;;) {

                }
            }
        });

        t1.start();

        Thread.sleep(10);

        t2.start();

        Thread.sleep(100);

        mutex.lock();

        System.out.println("Inside thread -> " + Thread.currentThread() + "will I get printed?");
    }
}

下面是这个程序的输出:

代码语言:javascript
复制
Inside thread -> Thread[Thread-0,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-0,5,main]After mutex.lock()
Inside thread -> Thread[Thread-1,5,main]Before mutex.lock()
Inside thread -> Thread[Thread-1,5,main]After mutex.lock()
Inside thread -> Thread[main,5,main]will I get printed?

Thread-1启动并获取锁,然后Thread-2调用unlock()。Main调用lock()。我的理解是,Main将永远被阻塞,即使线程-2调用了unlock(),因为线程-2从未调用过permit()(因此,它永远不会被授予锁)。

我不能理解这种行为。如果我在Thread-2中注释unlock(),那么main-thread将永远被阻塞。

一个线程(在我的例子中是Thread-2)调用unlock() (它以前没有调用lock()),而其他线程(在这个例子中是主线程)调用lock(),但从未被锁定,这是怎么可能的呢?

EN

回答 2

Stack Overflow用户

发布于 2021-01-30 18:49:55

如果深入研究源代码,unblock方法实际上会释放变量locked提供的CAS锁,并解除第一线程的驻留。因此,如果注释掉unlock()的调用,CAS锁不会被释放,并且主线程可能永远停留在while循环中,这会阻塞主线程。

票数 0
EN

Stack Overflow用户

发布于 2021-01-30 21:00:28

首先: FIFOMutex调用

代码语言:javascript
复制
Thread current = Thread.currentThread();

这意味着实际的线程被用于验证。这意味着考虑最实际的线程,也就是:

首先是

  • 线程1并发出锁定,然后调用
  • 线程2并发出解锁。

这就是为什么主线程不会挂起的原因。但是:如果您注释线程2的解锁,则没有执行任何操作,并且主线程挂起。这是很容易理解的,不是吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62396551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档