此程序尝试按顺序打印数字 1 到 10,第一个线程打印奇数,第二个线程打印偶数。
我一直在阅读 JCIP 的书,它说:
Ensure that the state variables making up the condition predicate are guarded by the lock associated with the condition queue.
在下面的程序中,条件队列将对应静态成员'obj1',而组成条件谓词的状态变量是静态volatile成员'count'。 (如果我对条件、状态变量、条件谓词的解释有误,请告诉我)
下面的程序可以正常工作,但显然违反了上面的习惯用法。我是否正确理解了作者的意思?下面的代码真的是一个糟糕的编程实践吗(恰好可以正常工作)
你能举个例子吗?如果不遵循上述习语,我会遇到问题吗?
public class OddEvenSynchronized implements Runnable {
static Object obj1 = new Object(); // monitor to share data
static volatile int count =1; // condition predicate
boolean isEven;
public OddEvenSynchronized(boolean isEven) { //constructor
this.isEven=isEven;
}
public void run (){
while (count<=10){
if (this.isEven == true){
printEven(); //print an even number
}
else{
printOdd(); //print an odd number
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread (new OddEvenSynchronized(true));
Thread t2 = new Thread (new OddEvenSynchronized(false));
//start the 2 threads
t1.start();
t2.start();
}
void printEven(){
synchronized (obj1) {
while (count%2 != 0){
try{
obj1.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Even"+count);
count++; //unguarded increment (violation)
synchronized (obj1) {
obj1.notifyAll();
}
} //end method
void printOdd(){
synchronized (obj1) {
while (count%2 == 0){
try{
obj1.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Odd"+count);
count++; //unguarded increment (violation)
synchronized (obj1) {
obj1.notifyAll();
}
} //end method
} //end class
最佳答案
如果您未在 obj1
上同步,请不要读取或写入 count
。那是不行不行!打印和增量应该在同步块(synchronized block)内完成。
synchronized (obj1) {
while (count%2 != 0){
try {
obj1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even"+count);
}
synchronized (obj1) {
count++;
obj1.notifyAll();
}
您会注意到现在没有理由放弃同步。合并这两个 block 。
synchronized (obj1) {
while (count%2 != 0){
try {
obj1.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Even"+count);
count++;
obj1.notifyAll();
}
The below program works correctly but is clearly violating the above idiom.
多线程编程的潜在危险在于,有缺陷的程序可能看起来大部分时间都能正常工作。竞争条件可能非常曲折,因为它们通常需要非常严格的时间条件,而这种情况很少发生。
严格遵守规则真的非常重要。正确地进行多线程编程非常困难。几乎可以肯定的是,只要您偏离规则并试图变得聪明,就会引入细微的错误。
关于java - 这是在 Java 中错误使用内部条件队列吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32280646/