V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mengxh1990
V2EX  ›  Java

关于 synchronized 的疑问

  •  
  •   mengxh1990 · 2018-02-13 22:49:41 +08:00 · 3071 次点击
    这是一个创建于 2510 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 代码块保证两个线程只有一个能够访问这块代码,其他的线程被阻塞,直到前面的线程执行完毕。但是上面这个例子,始终只有一个线程能执行,一个执行完之后另外的线程却不执行。请问这是怎么回事呢?请大神指点。
    8 条回复    2018-02-14 09:49:27 +08:00
    hand515
        1
    hand515  
       2018-02-13 23:11:50 +08:00
    你没 join
    sagaxu
        2
    sagaxu  
       2018-02-13 23:12:01 +08:00 via Android
    第一个线程执行完,while 已经不成立了
    bxb100
        3
    bxb100  
       2018-02-13 23:13:36 +08:00 via Android
    因为你的 while 循环啊
    hand515
        4
    hand515  
       2018-02-13 23:14:40 +08:00   ❤️ 2
    我上面说错了,你线程 1 已经吧 num 减到 0,线程 2 的 while 进不去
    pwrliang
        5
    pwrliang  
       2018-02-13 23:56:31 +08:00   ❤️ 2
    首先,synchronized 保护的是共享资源,你只创建了一个 TxtThread 实例这是对的,但这里面所有的成员变量都被这两个线程共享,也包括 num,但是你对 num--,这个操作不是原子操作,会造成 race condition,你应该用 AtomicInteger 之类的库。最后不要用 sleep 来等待线程完成,sleep 是不可靠的不一定保证 1000ms 后线程会被调度。应该用 join
    mengxh1990
        6
    mengxh1990  
    OP
       2018-02-14 09:37:52 +08:00
    @hand515 多谢指教
    mengxh1990
        7
    mengxh1990  
    OP
       2018-02-14 09:39:08 +08:00
    @sagaxu 是的,num 被两个线程共享,第一个线程已经把它改变了,thx~
    mengxh1990
        8
    mengxh1990  
    OP
       2018-02-14 09:49:27 +08:00   ❤️ 1
    @pwrliang 感谢指教,这里忽略了 num 是被两个线程共享的,第一个线程已经把 num 减为 0,第二个线程的循环条件就不成立了。另外,你提到的对 num 的操作会造成 race condition,这个竞争应该不会发生吧?因为 synchronized 已经保证了只有一个线程能访问到这块代码,即只有一个线程可以操作到成员变量 num,所以在 synchronized 的保护下,应该不会存在 num 上的竞争吧。不知道理解的对不对,还望指教。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2889 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 13:11 · PVG 21:11 · LAX 05:11 · JFK 08:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.