我的代码如下:这是为了获取信号量的知识。代码是线程A首先等待自b.wait()(使调用线程休眠),然后得到通知,为什么代码在这里同步?如果不是,则会给出IllegalMontiorXXXXXXXXX异常。
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(b){
try{
System.out.println("Waiting for b to complete...");
b.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Total is: " + b.total);
}
}
}
class ThreadB extends Thread{
int total;
@Override
public void run(){
synchronized(this){
for(int i=0; i<100 ; i++){
total += i;
}
notify();
}
}
}
编辑:答案是同步让当前线程拥有信号量。 notify()文档解释了这一点。
答案 0 :(得分:6)
您应该只使用最终对象作为监视器。它会为你节省一些讨厌的错误。
如果您的显示器未成为最终显示器,则始终有可能将其设置为 引用一个新对象,在这种情况下,看似同步的代码实际上会运行 在平行下。请阅读here了解更多信息。
以下是它的完成方式:
:一种。消费者:强>
static final Object monitor = new Object(); //<---------------
static volatile boolean completed = false;
public class ThreadA {
public static void main(String[] args){
ThreadB b = new ThreadB();
b.start();
synchronized(monitor) {
while (!completed) {
monitor.wait();
}
}
// when here: producer had completed <-----------------
}
}
<强> B中。生产者:强>
class ThreadB extends Thread{
int total;
@Override
public void run(){
for(int i=0; i<100 ; i++) { //<------------ no need to synchronize
total += i;
}
completed = true; <--------- mark producer as completed
synchronized(monitor) {
monitor.notify();
}
}
}
答案 1 :(得分:0)
也可以使用Semaphore,或者在这种情况下使用CountDownLatch。查看source code for Semaphore,等待并通知表面。
使用CountDownLatch使代码更易于阅读:
import java.util.concurrent.CountDownLatch;
public class WaitOnCount {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(1);
ThreadB b = new ThreadB(latch);
b.start();
try {
latch.await();
System.out.println("Total is: " + b.total);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class ThreadB extends Thread {
final CountDownLatch latch;
int total;
ThreadB(CountDownLatch latch) {
super();
this.latch = latch;
}
@Override
public void run() {
for(int i = 0; i < 100; i++) {
total += i;
}
latch.countDown();
}
}
}