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

关于 synchronized 的疑问

  •  
  •   mengxh1990 2018-02-13 22:49:41 +08:00 3420 次点击
    这是一个创建于 2798 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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
    Finest
        1
    Finest  
       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 循环啊
    Finest
        4
    Finest  
       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     Solana     5560 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 07:18 PVG 15:18 LAX 00:18 JFK 03:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86