java - 如何使用信号量进行信号发送?

标签 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
...

我尝试使用这个蓝图编写自己的代码

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

因此这不是我预期的行为。

我写代码时犯了错误还是我不理解概念?

作者想表达什么?

最佳答案

寻找更好的教程。

您看到的输出与我所期望的差不多。 “sender”线程从不阻塞,所以它将永远打印“send”、“send”、“send”。同时,在“接收方”线程中,每次调用 semaphore.release() 方法时,它将被阻塞,直到发送方下次运行。

我希望看到很多“发送”消息,偶尔会混入“接收”消息——或多或少如您描述的那样。

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

一些作者提供了应该做的事的例子,或者包含将在后面的例子中“修正”的蓄意错误的例子。您确定您没有在遵循此类示例吗?

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

关于java - 如何使用信号量进行信号发送?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23255267/

相关文章:

java - IllegalAccessError 仅在导出的签名 APK 上

java - 在多线程程序中更新共享资源

java - 更新 Java Swing JList

java - 什么时候 AtomicInteger 优于同步?

java - 使用 Docker 的 Java 开发工作流程/反馈循环缓慢 : do I need to rebuild the JAR and image after every change?

javascript - 来自 Web 的 Firebase 云 HTTP 消息

java - 使用 shell 脚本比较两个 java 属性文件

C# : Whether this approach is thread-safe

Java 等待/通知全部

c# - 两个 .NET 线程和硬件访问的问题