Main.java:
public class Main {
public static void main(String[] args) {
final Semaphore semp = new Semaphore(1);
for (int facultyNO = 1; facultyNO <= 10; facultyNO++) {
final int NO = facultyNO;
Runnable run = new Runnable() {
public void run() {
try {
while (true) {
semp.acquire();
System.out.println("No." + NO + " grab a candy");
Bowl.candy--;
System.out.println("Candy num left:" + Bowl.candy);
semp.release();
Thread.sleep((long) (1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread faculty = new Thread(run);
faculty.setPriority(Thread.MIN_PRIORITY);
faculty.start();
}
Thread TA = new Thread(() -> {
try {
while (true) {
if (Bowl.candy < 0) {
semp.acquire();
System.out.println("TA fills the candy bowl");
Bowl.candy = 10;
System.out.println("Candy num left:" + Bowl.candy);
semp.release();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
});
TA.setPriority(Thread.MAX_PRIORITY);
TA.start();
}
}
Bowl.java:
public class Bowl {
static int candy = 10;
}
我给线程&#34; TA&#34;最高优先级,因为我希望它在Bowl.candy = 0时尽快执行以填充碗。但是,控制台打印:
No.2 grab a candy
Candy num left:9
No.1 grab a candy
Candy num left:8
No.4 grab a candy
Candy num left:7
No.6 grab a candy
Candy num left:6
No.7 grab a candy
Candy num left:5
No.8 grab a candy
Candy num left:4
No.3 grab a candy
Candy num left:3
No.5 grab a candy
Candy num left:2
No.10 grab a candy
Candy num left:1
No.9 grab a candy
Candy num left:0
No.2 grab a candy
Candy num left:-1
No.1 grab a candy
Candy num left:-2
No.4 grab a candy
Candy num left:-3
No.6 grab a candy
Candy num left:-4
No.7 grab a candy
Candy num left:-5
No.8 grab a candy
Candy num left:-6
No.3 grab a candy
Candy num left:-7
No.5 grab a candy
Candy num left:-8
No.10 grab a candy
Candy num left:-9
No.9 grab a candy
Candy num left:-10
似乎if (Bowl.candy < 0)
中的代码永远不会被执行。为什么呢?
答案 0 :(得分:3)
在这种情况下,您必须先获取锁定才能访问变量:
semp.acquire();
if (Bowl.candy < 0) {
System.out.println("TA fills the candy bowl");
Bowl.candy = 10;
System.out.println("Candy num left:" + Bowl.candy);
}
semp.release();
另一种选择:
Bowl.candy
必须声明为volatile
,否则无法保证其他线程可以看到对此变量的更改。或者只能在Bowl.candy
块中访问synchronized
。
答案 1 :(得分:1)
我怀疑这是一个竞争条件问题。您正在检查该值,然后我怀疑另一个线程已经采用了信号量,因此您无法更改该值。
如果您更改信号量以包装支票和分配,您的结果会稍微好一点。
Thread TA = new Thread(() -> {
try {
while (true) {
semp.acquire();
if (candy < 0) {
System.out.println("TA fills the candy bowl");
Bowl.candy = 10;
System.out.println("Candy num left:" + Bowl.candy);
}
semp.release();
}
}
//...
});
但是,由于时间安排问题,您将获得以下结果:
Candy num left:2
No.2 grab a candy
Candy num left:1
No.3 grab a candy
Candy num left:0
No.5 grab a candy
Candy num left:-1 //!!!
No.6 grab a candy
Candy num left:-2 //!!!
TA fills the candy bowl
正如Nambari指出的那样,你可能不想用多个线程来解决这个问题。