我正在阅读在JAVA中思考(Ed4,由Bruce Eckel撰写),其中说:
请注意,在将字段设为私有时尤为重要 使用并发;否则synchronized关键字不能 防止另一个任务直接访问字段,从而 产生碰撞。
我很困惑,最后得到这个demo:
public class SimpleSerial {
public static void main(String[] args) throws IOException {
ShareObject so = new ShareObject();
Thread thread1 = new Thread(new ThreadOperation(so, "add"));
Thread thread2 = new Thread(new ThreadOperation(so, "sub"));
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
System.out.println("Press Enter to stop");
System.in.read();
System.out.println("Now, a=" + so.a + " b=" + so.b);
}
}
class ThreadOperation implements Runnable {
private String operation;
private ShareObject so;
public ThreadOperation(ShareObject so, String oper) {
this.operation = oper;
this.so = so;
}
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
}
}
}
class ShareObject {
int a = 100;
int b = 100;
public synchronized void add() {
++a;
++b;
}
public synchronized void sub() {
--a;
--b;
}
}
每次a
和b
的值都不同时。那为什么呢?
该演示还提到了线程sleep()是否短时间,即重新编写ThreadOperation
中的run()方法:
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后a
和b
的值相同。
再说一遍,为什么? sleep()
背后会发生什么?
答案 0 :(得分:0)
使用sleep()
,当线程处于休眠状态时,println()
很可能会执行。该程序仍然非线程安全。
您可以通过向synchronized
添加print()
SharedObject
方法来解决此问题,例如:
public synchronized void print() {
System.out.println("Now, a=" + a + " b=" + b);
}
并在main
的最后一行调用它,而不是当前未同步的访问。