2013-03-08 61 views
0

对于一项任务,我必须在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()和相反我怎么解锁的信号一个线程()?我读到有一个阻塞的队列,但我会在那里保持对该队列的引用?

+0

你允许为此使用什么锁定基元? [对象#wait()的(http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait())? – 2013-03-08 17:41:27

+1

为什么不实现'wait()'和'signal()'作为实例方法?按照定义,信号量由多个线程调用。您需要同步才能使代码线程安全。 (注意'wait()'应该被命名为'await()'(或其他),因为Object有一个'wait()'方法) – 2013-03-08 17:45:16

回答

1

在您的等待方法中(应该将其称为别的事情而不是等待),您需要检查您的值为零,如果它为零,你只是在等待。这可以通过以下方式来实现:

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

您的方法不需要信号量对象。您只需在Semaphore类中使用值字段。

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

您的信号方法需要递增该值,并通知正在等待值已更改的线程以查看是否可以进入其临界区。信号方法在以下实施:

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

我用的方法的命名来自于Dijkstra算法用于信号量的名字(以防万一你被他们混淆)。

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

+1

+1这个回答请求。顺便说一下P()和V(),因为Dijkstra来自荷兰,并使用本国语言进行这些功能。 – 2013-03-08 19:38:36

+0

谢谢,这帮了我很多! – Ziamor 2013-03-08 19:50:49

0

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