如何使用信号量进行信令?

时间:2014-04-23 21:12:25

标签: java multithreading concurrency synchronization semaphore

现在我调查信号量。我用谷歌搜索了关于这个主题的链接:

link

此链接的作者写了关于使用信号量进行信令的文章。为了说明它是如何工作的,他编写了自定义信号量。

自定义信号量代码:

public class Semaphore {
  private boolean signal = false;

  public synchronized void take() {
    this.signal = true;
    this.notify();
  }

  public synchronized void release() throws InterruptedException{
    while(!this.signal) wait();
    this.signal = false;
  }

}

关于如何在他编写的代码中使用它:

public class SendingThread {
  Semaphore semaphore = null;

  public SendingThread(Semaphore semaphore){
    this.semaphore = semaphore;
  }

  public void run(){
    while(true){
      //do something, then signal
      this.semaphore.take();

    }
  }
}



public class RecevingThread {
  Semaphore semaphore = null;

  public ReceivingThread(Semaphore semaphore){
    this.semaphore = semaphore;
  }

  public void run(){
    while(true){
      this.semaphore.release();
      //receive signal, then do something...
    }
  }
}

主:

Semaphore semaphore = new Semaphore();

SendingThread sender = new SendingThread(semaphore);

ReceivingThread receiver = new ReceivingThread(semaphore);

receiver.start();
sender.start();

据我所知,执行顺序应遵循

send - receive
send - receive
send - receive
...

我尝试使用此bluerprint编写自己的代码

public class SendReceiveWithCustomSemaphore {
    public static void main(String[] args) {
        MySemaphore mySemaphore = new MySemaphore();
        new Send(mySemaphore).start();
        new Receive(mySemaphore).start();
    }
}

class MySemaphore {
    boolean flag = false;

    public synchronized void take() throws InterruptedException {
        flag = true;
        notify();
    }

    public synchronized void release() throws InterruptedException {
        while (!flag) {
            wait();
        }
        flag = false;
    }
}

class Send extends Thread {
    MySemaphore mySemaphore;

    public Send(MySemaphore semaphore) {
        this.mySemaphore = semaphore;
    }

    @Override
    public void run() {
        int i = 0;
        while (i++ < 10) {
            System.out.println("send");
            try {
                mySemaphore.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Receive extends Thread {
    MySemaphore mySemaphore;

    public Receive(MySemaphore semaphore) {
        this.mySemaphore = semaphore;
    }

    @Override
    public void run() {
        while (true) {
            try {
                mySemaphore.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("receive");
        }
    }
}

输出:

send
send
send
send
send
send
send
send
send
send
receive

因此,对我来说这不是预期的行为。

我犯了一个错误然后我写了代码或者我不理解概念?

作者想说什么?

2 个答案:

答案 0 :(得分:4)

找一个更好的教程。

您看到的输出是关于我期望的。 &#34;发件人&#34;线程从不阻止,因此它将继续打印&#34;发送&#34;,&#34;发送&#34;,&#34;发送&#34;永远。同时,在&#34;接收器&#34;线程,每次调用semaphore.release()方法时,它都会被阻塞,直到下次发送者运行。

我希望看到很多&#34;发送&#34;消息,偶尔&#34;收到&#34;混合的信息 - 或多或少你所描述的。

我不知道那个例子应该证明什么,但对我来说,它给人的印象是作者不知道程序员如何期待信号量的表现。

一些作者提供了要做的事情的示例,或者包含将被修复的故意错误的示例&#34;在后面的例子中。你确定你没有关注那种例子吗?

编辑:我跟着链接,看起来主要的问题是名称在take()和release()方法的定义中交换。如果您只是切换名称,那就更有意义了。

答案 1 :(得分:1)

当ReceiveSemafore启动时,SendSemafore已经执行了10次。

考虑使用CountDownLatch同时启动两个线程。虽然正如Fuhrmanator所指出的那样,这不会产生您正在寻找的交替输出。

为此我会使用带有一个信号的有界信号量。