【问题标题】:Semaphore how to block and unblock信号量如何阻塞和解除阻塞
【发布时间】:2013-03-08 17:40:08
【问题描述】:

对于一项作业,我必须在 Java 中创建一个计数信号量。到目前为止,我已经创建了这个最基本的类

public class Semaphore {
    int value;

    public Semaphore(int value) {
        this.value = value;
    }

    public static void wait(Semaphore s) {
        s.value--;
        if (s.value < 0) {
            // block
        }
    }

    public static void signal(Semaphore s) {
        s.value++;
        if (s.value <= 0) {
            // unblock one process that is blocked on semaphore
        }

    }   
}

现在我感到困惑的是,我究竟如何在 wait() 上阻塞,相反,我如何在 signal() 上解除阻塞一个线程?我读到有一个被阻塞的队列,但我会在哪里继续引用该队列?

【问题讨论】:

  • 您可以为此使用哪些锁定原语? Object#wait()?
  • 为什么不实现wait()signal() 作为实例方法呢?根据定义,信号量由多个线程调用。您需要同步以使代码线程安全。 (注意 wait() 应该命名为 await() (或其他名称),因为 Object 已经有一个 wait() 方法)

标签: java signals block semaphore wait


【解决方案1】:

在您的等待方法(应该称为等待以外的其他方法)中,您需要检查您的值是否为零,如果为零,则继续等待。这是通过以下方式实现的:

public synchronized void P() throws InterruptedException 
{
    while (value == 0) 
    {
        wait();
    }
    value--;
}

您的方法不采用 Semaphore 对象。您只需在 Semaphore 类中使用 value 字段。

该方法检查当值为 0 时,它等待值被更改。因此,您调用该方法的线程将不得不等待。否则,如果该值不为零,则线程可以进入其临界区,并且该值会递减,直到再次为零,这就是线程阻塞的时候。

你的信号方法需要增加值,并通知正在等待值发生变化的线程,看它是否可以进入它的临界区。信号方法实现如下:

public synchronized void V() 
{
    value++;
    notify();
}

我用于方法的命名来自 Dijkstra 用于信号量的名称(以防您被它们混淆)。

您不应该调用阻塞方法等待,因为它会与 Object 的等待方法混淆。

【讨论】:

  • +1 这回答了请求。顺便说一句,P() 和 V() 因为 Dijkstra 来自荷兰,并且使用母语来实现这些功能。
  • 谢谢你,这对我帮助很大!
【解决方案2】:

看看使用 wait()/notify() 方法。在调用这些之前需要获取对象锁。这意味着您必须将方法设为非静态并将它们标记为同步

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    相关资源
    最近更新 更多