Java 与多线程服务器的繁忙循环相比,互斥体导致丢失输入?
Java mutex causing missing input compared to busy loop for multithreaded server?
我正在编写一个 Java 程序,它与我的 Linux 服务器上的 C 程序接口(这是一个 client/server 聊天程序)。现在,我正在为输入实施阻塞功能,直到用户在将输入发送到服务器之前按下“Enter”。为此,我有两个选择:忙循环和互斥锁。互斥锁显然是最好的选择,但我 运行 遇到一个问题,有时输入根本不会发送到服务器。不过,在繁忙的循环中,我只是取消了一个标志,它工作正常。
忙循环:
while(!this.inputField.isReady()){}
// send data in inputField to server
this.inputField.setReady(false);
所以,我需要在文本字段中(在键盘监听器中)做的是:
...
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,但没有用。任何帮助将不胜感激。
你的互斥体什么都不做。它没有保护任何东西。
如果共享状态是就绪标志,那么互斥量必须保护就绪标志。所以:
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
returns 之后但在您输入 wait
.
之前更改状态,则会产生竞争条件
我正在编写一个 Java 程序,它与我的 Linux 服务器上的 C 程序接口(这是一个 client/server 聊天程序)。现在,我正在为输入实施阻塞功能,直到用户在将输入发送到服务器之前按下“Enter”。为此,我有两个选择:忙循环和互斥锁。互斥锁显然是最好的选择,但我 运行 遇到一个问题,有时输入根本不会发送到服务器。不过,在繁忙的循环中,我只是取消了一个标志,它工作正常。
忙循环:
while(!this.inputField.isReady()){}
// send data in inputField to server
this.inputField.setReady(false);
所以,我需要在文本字段中(在键盘监听器中)做的是:
...
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,但没有用。任何帮助将不胜感激。
你的互斥体什么都不做。它没有保护任何东西。
如果共享状态是就绪标志,那么互斥量必须保护就绪标志。所以:
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
returns 之后但在您输入 wait
.