Java 我的线程没有';我得不到通知,我的程序挂起
下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样?notifyall应该唤醒所有处于等待状态的线程Java 我的线程没有';我得不到通知,我的程序挂起,java,multithreading,synchronization,java-threads,Java,Multithreading,Synchronization,Java Threads,下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样?notifyall应该唤醒所有处于等待状态的线程 public class Testing { public static void main(String[] args) { Testing testing=new Testing(); testing.reader.start(); testing.writer.start(); } Thread
public class Testing {
public static void main(String[] args) {
Testing testing=new Testing();
testing.reader.start();
testing.writer.start();
}
Thread reader = new Thread("reader") {
public void run() {
System.out.println("reader started");
synchronized (this) {
try {
wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
for (int i = 0; i < 10; i++) {
System.out.println("reader " + i);
}
}
};
Thread writer = new Thread("writer") {
public void run() {
System.out.println("writer started");
for (int i = 0; i < 10; i++) {
System.out.println("writer " + i);
}
synchronized (Thread.currentThread()) {
notifyAll();
}
}
};
}
公共类测试{
公共静态void main(字符串[]args){
测试=新测试();
testing.reader.start();
testing.writer.start();
}
线程读取器=新线程(“读取器”){
公开募捐{
System.out.println(“读卡器已启动”);
已同步(此){
试一试{
等待();
}捕获(中断异常例外){
例如printStackTrace();
}
}
对于(int i=0;i<10;i++){
System.out.println(“读卡器”+i);
}
}
};
线程编写器=新线程(“编写器”){
公开募捐{
System.out.println(“编写器启动”);
对于(int i=0;i<10;i++){
System.out.println(“writer”+i);
}
已同步(Thread.currentThread()){
notifyAll();
}
}
};
}
NotifyAll()不属于Thread类,而是属于Object基类;在Thread writer中,NotifyAll()是writer Object的函数,可以唤醒具有writer对象锁的线程; 下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样 您的程序未完成,因为写入线程终止,但读取器线程卡在
wait()
中。代码的问题是读线程正在等待它自己的线程对象,而写线程正在通知它自己的线程对象,这是不同的。您需要做的是让它们在同一个对象实例上等待并通知
快速修复方法是使用静态锁定对象:
private static final Object lockObject = new Object();
// reader:
synchronized (lockObject) {
lockObject.wait();
...
// writer
synchronized (lockObject) {
lockObject.notify();
然后读写器都在锁定、等待和通知同一个最终对象实例。在无法更改的字段上进行同步是一种很好的模式,因此private final Object
或类似的字段是最好的。另外,您只有一个线程,因此notify()
就足够了
但是,您的代码仍然存在争用条件问题。在读取器到达wait()
之前,您的编写器可以调用notifyAll()
(尽管可能性不大)。如果通知发生,并且没有人等待,那么这是一个noop,读卡器在到达wait()
时将挂起
更好的解决方案是使用共享的AtomicBoolean
:
private final AtomicBoolean writerDone = new AtomicBoolean();
...
// reader
while (!writerDone.get()) {
synchronized (writerDone) {
writerDone.wait();
}
}
// writer
writerDone.set(true);
synchronized (writerDone) {
writerDone.notifyAll();
}
您只需做少量更改,如下所示:
public static void threadTest(){
Test testing = new Test();
testing.lock = new Object();
testing.reader.start();
testing.writer.start();
}
private Object lock;
Thread reader = new Thread("reader") {
public void run() {
System.out.println("reader started");
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
for (int i = 0; i < 10; i++) {
System.out.println("reader " + i);
}
}
};
Thread writer = new Thread("writer") {
public void run() {
System.out.println("writer started");
for (int i = 0; i < 10; i++) {
System.out.println("writer " + i);
}
synchronized (lock) {
lock.notifyAll();
}
}
};
publicstaticvoidthreadtest(){
测试=新测试();
testing.lock=新对象();
testing.reader.start();
testing.writer.start();
}
私有对象锁;
线程读取器=新线程(“读取器”){
公开募捐{
System.out.println(“读卡器已启动”);
已同步(锁定){
试一试{
lock.wait();
}捕获(中断异常例外){
例如printStackTrace();
}
}
对于(int i=0;i<10;i++){
System.out.println(“读卡器”+i);
}
}
};
线程编写器=新线程(“编写器”){
公开募捐{
System.out.println(“编写器启动”);
对于(int i=0;i<10;i++){
System.out.println(“writer”+i);
}
已同步(锁定){
lock.notifyAll();
}
}
};
yes调用当前线程时返回读线程。但是notify和notifyall都不会唤醒等待的线程。oops!这是一个错误。我将向writer更正。实际上,现在返回的当前线程是writer。您能否帮助我了解如何通知读线程。在未事先确认synchronized
块内您等待的事情尚未发生之前,请不要调用wait
。在调用wait
后,在未确认等待的事情已经发生之前,不要离开synchronized
块。(此外,编写器调用notifyAll
,而没有更改synchronized
块中的任何内容,因此没有任何需要通知的内容。)