问题描述
我找不到问题有人可以帮助我。
public class Achterbahn {
private final Object monitor = new Object();
public synchronized void test() throws InterruptedException {
//monitor.wait();
System.out.println("car");
wait();
System.out.println("car");
}
public synchronized void Passagier() throws InterruptedException {
Thread.sleep(2000);
System.out.println("p");
notify();
//b.t1.notify();
}
public static void main(String []args) throws InterruptedException {
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
Achterbahn b = new Achterbahn();
try {
b.Passagier();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t5= new Thread(new Runnable() {
@Override
public void run() {
Achterbahn b = new Achterbahn();
try {
b.test();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
new Thread(t4).start();
new Thread(t5).start();
t5.join();
t4.join();
}
}
输出为: 车
似乎通知正在工作,我最后还想打印汽车,但我不知道为什么它不起作用
我希望有人帮助我。尽快。
我在同一个类中有所有方法,我也尝试过单独的类,但没有用
解决方法
(我猜在这种情况下“它不起作用”意味着程序挂起。请具体说明您看到的问题是什么。)
有两个问题。一种是您在每个线程中创建单独的对象。等待和通知被调用的对象必须是相同的,等待的监视器是需要接收通知的监视器。在这段代码中,同步方法在调用方法的实例上使用了内在锁。
在main方法中创建一次对象,每个线程需要引用同一个对象。
第二个问题,一旦你解决了第一个问题,就会成为竞争条件。如果一个线程执行的通知首先发生,那么当等待执行时,通知已经发生并且等待永远等待。
添加条件变量以记住通知是否发生。
通常模式是在循环中检查条件,请参阅此问题:Why we must use "while" for checking race condition not "if"。该帖子有一个使用变量查看条件是否发生的示例,这里是
synchronized(obj)
{
while (condition_not_matched)
{
obj.wait();
}
//continue
dosomething();
}
,
你做错了几件事。
- 仅启动 C 的单个实例。然后使用该实例调用您的方法。不同的实例在同步方法内不共享监视器
- 当您启动它们时,您正在启动两个新线程。只需按如下方式启动它们:
t4.start();
t5.start();
主要问题是 t4
首先启动并立即休眠。所以 t5
在睡眠结束之前不会开始。但是到那时,notify()
中等待的 t4
已经之前发出,wait()
在 t5
中被调用 因此 {{1 }} 永远不会看到它。因此,您需要在睡眠发生之前给 wait
一个开始的机会。有几种方法可以解决这个问题。一种是使用标志来表示另一种方法已准备就绪。但不要使用紧凑的 while 循环。将 t4
放入其中一小段时间。我在下面提供了一个例子。我还为您的线程分配了名称以匹配您的变量。
sleep
,
此代码对我有用,我现在有了 while 循环
public class C {
int i = 34;
public synchronized void test() throws InterruptedException {
System.out.println("car");
while(i == 34) {
wait();
}
notify();
System.out.println("car");
}
public synchronized void Passagier() throws InterruptedException {
i = 55;
System.out.println("p");
notify();
}
public static void main(String[] args)
throws InterruptedException {
C b = new C();
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
try {
b.Passagier();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
Thread t5 = new Thread(new Runnable() {
@Override
public void run() {
try {
b.test();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t4.start();
t5.start();
t4.join();
t5.join();
}
}