与多线程服务器的繁忙循环相比,Java 互斥体导致输入丢失?
Posted
技术标签:
【中文标题】与多线程服务器的繁忙循环相比,Java 互斥体导致输入丢失?【英文标题】:Java mutex causing missing input compared to busy loop for multithreaded server? 【发布时间】:2021-07-23 23:31:33 【问题描述】:我正在编写一个与我的 Linux 服务器上的 C 程序交互的 Java 程序(它是一个客户端/服务器聊天程序)。现在,我正在为输入实现阻塞功能,直到用户在将输入发送到服务器之前按下“Enter”。为此,我有两个选择:繁忙循环和互斥锁。互斥锁显然是最好的选择,但我遇到了一个问题,有时输入根本不会发送到服务器。不过,在繁忙的循环中,我只需取消设置一个标志,它就可以正常工作。
忙循环:
while(!this.inputField.isReady())
// send data in inputField to server
this.inputField.setReady(false);
所以,我需要在文本字段中(在 keylistener 中)做的是:
...
public void keyPressed(KeyEvent e)
if (e.getKeyCode() == KeyEvent.VK_ENTER)
ready = true;
setText("");
...
所以,是的,这行得通。我的互斥锁解决方案就没那么幸运了:
while (!this.inputField.isReady())
synchronized(this.inputField.mutex)
try
this.inputField.mutex.wait();
... //redacted for simplicity
还有通知者:
...
ready = true;
// This is in the TextField class.
synchronized(this.mutex)
this.mutex.notify();
setText("");
...
也许我误解了 Java 同步功能的一个基本部分(这在 C 中要容易得多......)。互斥锁只是一个标准对象,遵循在线示例。请注意,我确实尝试了 notifyAll,但这没有用。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:你的互斥锁什么都不做。它无法保护任何东西。
如果共享状态是就绪标志,则互斥锁必须保护就绪标志。所以:
synchronized(this.inputField.mutex)
while (!this.inputField.isReady())
try
this.inputField.mutex.wait();
... //redacted for simplicity
请注意,您不能在不持有互斥锁的情况下调用isReady
,因为互斥锁会保护准备就绪时的同步。同样:
...
// This is in the TextField class.
synchronized(this.mutex)
ready = true;
this.mutex.notify();
setText("");
...
互斥锁必须保护共享状态。如果共享状态是就绪标志,则任何线程都不能在不持有互斥体的情况下访问就绪标志。
您没有展示您对isReady
的实现,但如果它本身获取互斥锁,那就不够了。您无法获取互斥体、检查就绪、释放互斥体,然后调用wait
。如果在 isReady
返回之后但在您输入 wait
之前准备好标志更改状态,则会产生竞争条件。
【讨论】:
以上是关于与多线程服务器的繁忙循环相比,Java 互斥体导致输入丢失?的主要内容,如果未能解决你的问题,请参考以下文章