按序打印
程序员文章站
2022-07-14 08:02:24
...
按序打印
一开始这样写的,错了,大家知道为什么吗?
class Foo {
private int volatile n = 0;
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
synchronized (this){
if(n % 3 == 0){
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
n += 1;
notifyAll();
}else {
wait();
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
synchronized (this) {
if (n % 3 == 1) {
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
n += 1;
notifyAll();
} else {
wait();
}
}
}
public void third(Runnable printThird) throws InterruptedException {
synchronized (this) {
if (n % 3 == 2) {
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
n += 1;
notifyAll();
} else {
wait();
}
}
}
}
其实错就错在:
else {
wait();
}
这里了,因为如果second和third先执行,然后first执行,导致只能输出first,不能输出second和third,因为wait被notify后,不会再次执行函数体。
改成下面的代码就ok了:
package 多线程;
class Foo {
private volatile int n = 0;
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
synchronized (this){
while(n % 3 != 0){
wait();
}
if(n % 3 == 0){
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
n += 1;
notifyAll();
}
}
}
public void second(Runnable printSecond) throws InterruptedException {
synchronized (this) {
while(n % 3 != 1){
wait();
}
if (n % 3 == 1) {
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
n += 1;
notifyAll();
}
}
}
public void third(Runnable printThird) throws InterruptedException {
synchronized (this) {
while(n % 3 != 2){
wait();
}
if (n % 3 == 2) {
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
n += 1;
notifyAll();
}
}
}
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(new Runnable() {
@Override
public void run() {
try {
foo.first();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
foo.second();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
try {
foo.third();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
这里能够保证,拿到锁,继续执行下面的方法。
while(n % 3 != 1){
wait();
}