我有下面的代码:这是获得信号量的知识。代码是线程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()文档解释了
应该只使用final对象作为监视器。这会帮你避免一些讨厌的虫子。
如果你的显示器不是最终的,总是有机会它将被设置为引用一个新对象,在这种情况下,看起来同步的代码实际上会运行并行执行。点击这里了解更多。
是这样做的:
。消费者:
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();
}
}
}
不妨使用信号量,或者在本例中使用CountDownLatch。看一下Semaphore的源代码,wait和notify仅仅触及了表面。
使用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();
}
}
}