关于 synchronized 的疑问

2018-02-13 22:49:41 +08:00
 mengxh1990
public class TextThread {
public static void main(String[] args) {
TxtThread tt = new TxtThread();
new Thread(tt).start();
new Thread(tt).start();
try {
Thread.sleep(1000);
}catch (Exception e) {
e.getMessage();
}
}
}

class TxtThread implements Runnable {
int num = 10;
String str = new String();
public void run() {
synchronized (str) {
while (num > 0) {
try {
Thread.sleep(1);
}catch (Exception e) {
e.getMessage();
}
System.out.println(Thread.currentThread().getName() + "this is " + num--);
}
}
}
}

synchronized 代码块保证两个线程只有一个能够访问这块代码,其他的线程被阻塞,直到前面的线程执行完毕。但是上面这个例子,始终只有一个线程能执行,一个执行完之后另外的线程却不执行。请问这是怎么回事呢?请大神指点。
2902 次点击
所在节点    Java
8 条回复
hand515
2018-02-13 23:11:50 +08:00
你没 join
sagaxu
2018-02-13 23:12:01 +08:00
第一个线程执行完,while 已经不成立了
bxb100
2018-02-13 23:13:36 +08:00
因为你的 while 循环啊
hand515
2018-02-13 23:14:40 +08:00
我上面说错了,你线程 1 已经吧 num 减到 0,线程 2 的 while 进不去
pwrliang
2018-02-13 23:56:31 +08:00
首先,synchronized 保护的是共享资源,你只创建了一个 TxtThread 实例这是对的,但这里面所有的成员变量都被这两个线程共享,也包括 num,但是你对 num--,这个操作不是原子操作,会造成 race condition,你应该用 AtomicInteger 之类的库。最后不要用 sleep 来等待线程完成,sleep 是不可靠的不一定保证 1000ms 后线程会被调度。应该用 join
mengxh1990
2018-02-14 09:37:52 +08:00
@hand515 多谢指教
mengxh1990
2018-02-14 09:39:08 +08:00
@sagaxu 是的,num 被两个线程共享,第一个线程已经把它改变了,thx~
mengxh1990
2018-02-14 09:49:27 +08:00
@pwrliang 感谢指教,这里忽略了 num 是被两个线程共享的,第一个线程已经把 num 减为 0,第二个线程的循环条件就不成立了。另外,你提到的对 num 的操作会造成 race condition,这个竞争应该不会发生吧?因为 synchronized 已经保证了只有一个线程能访问到这块代码,即只有一个线程可以操作到成员变量 num,所以在 synchronized 的保护下,应该不会存在 num 上的竞争吧。不知道理解的对不对,还望指教。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/430645

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX