Android 上使用 wait/notify 的奇怪 bug - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gramyang
V2EX    Java

Android 上使用 wait/notify 的奇怪 bug

  •  
  •   gramyang 2019-11-27 18:25:30 +08:00 4851 次点击
    这是一个创建于 2145 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在主线程连接了 socket,在异步的准备工作做好了解除主线程阻塞。

    主线程阻塞:
    mCOnnectThread= new ConnectionManagerImpl.ConnectionThread(" Connect thread for " + info);
    mConnectThread.setDaemon(true);
    mConnectThread.start();
    synchronized (mConnectThread) {
    try {
    mConnectThread.wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    子线程初始化成功后解除主线程阻塞:
    在子 Thread 的 run()中
    synchronized (this) {
    this.notifyAll();
    }

    结果 android 主线程直接无限阻塞了。。。。求大佬支招
    17 条回复    2019-11-29 07:33:02 +08:00
    Kamiyu0087
        1
    Kamiyu0087  
       2019-11-27 18:38:22 +08:00
    把 mConnectThread.start(); 放到 synchronized 块里执行
    你这 wait() 的时候有可能 notifyAll() 已经跑过了
    gramyang
        2
    gramyang  
    OP
       2019-11-27 20:29:46 +08:00
    @Kamiyu0087 mConnectThread.start()不在 synchronized 块里面啊
    Aruforce
        3
    Aruforce  
       2019-11-27 20:56:46 +08:00 via Android
    Synchro 里面的代码块 写 thread.currenthread.wait……你这 Java 真差的可以…
    Aruforce
        4
    Aruforce  
       2019-11-27 20:58:39 +08:00 via Android
    #3

    synchronized (mConnectThread) {
    try {
    Thread.currentThread().wait();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    falsemask
        5
    falsemask  
       2019-11-27 22:21:39 +08:00
    子线程 syn 的 this 是 mConnectThread 对象吗
    falsemask
        6
    falsemask  
       2019-11-27 22:24:02 +08:00
    @Aruforce 你要不要试试你写的代码,你 synchronized 获取了 mConnectThread 的锁,然后在 Thread.currentThread()上 wait,你确定不会抛异常?
    gramyang
        8
    gramyang  
    OP
       2019-11-28 07:31:17 +08:00
    @falsemask 是的
    gramyang
        9
    gramyang  
    OP
       2019-11-28 07:32:08 +08:00
    @falsemask 所以我最烦这种没长眼睛,上来就秀优越感的人,v 站特别多,水平不怎么样还特爱装逼,我都懒得搭理
    gramyang
        10
    gramyang  
    OP
       2019-11-28 07:41:48 +08:00
    @Kamiyu0087
    @hhx
    我测试了一下,不行。果然还是我猜测的那样,android 里面的主线程是不能阻塞的,只要手动 wait 就会卡死。。。必须放到子线程里面去才行
    Aruforce
        11
    Aruforce  
       2019-11-28 08:09:35 +08:00 via Android
    @falsemask 抛什么异常? Illegal monitor ?别逗…
    GuuJiang
        12
    GuuJiang  
       2019-11-28 09:49:17 +08:00
    这是一个对 monitor 对象及 wait/notify/notifyAll 等方法的典型误解,要注意这几个方法是定义在 Object 类里的,从逻辑上来说 monitor 对象表示的是你需要控制互斥及同步访问的资源本身,而不是线程,这就是为什么很多代码里会有类似 Object lock = new Object()这样的语句,作为 monitor 的对象只需要跟你想要控制的资源有个一一对应的关系即可,基本不会有把 Thread 对象作为 monitor 的需求

    jdk 源码的 Thread.join 方法的注释里有这样一句话

    It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
    gramyang
        13
    gramyang  
    OP
       2019-11-28 10:37:13 +08:00
    @GuuJiang 关键是我现在的需求就是保证一个线程阻塞直至另一个线程执行完后再执行,而 android 的主线程不允许有任何阻塞的操作,至于是用 object 的 wait 还是 condition 的 wait 还是 future 的 get 没有区别。
    BrokenVns
        14
    BrokenVns  
       2019-11-28 12:40:57 +08:00
    1.主线程是可以有阻塞操作的,但不建议。
    2.我觉得你的 synchronized (mConnectThread)和 synchronized (this)可能不是同一对象,你这个 this 是 Thread 还是 Runnable ?我建议你把这两个对象打印出来看一下。
    3.你可以试试定义额外的对象作为锁来试试,比如都使用 synchronized (lockObject)
    gramyang
        15
    gramyang  
    OP
       2019-11-28 17:53:57 +08:00
    @BrokenVns mConnectThread 和 this 是同一个对象,this 是 Thread 的子类。synchronized (object)和 synchronized (this)应该是一样的吧?前提是 object 和 this 都是只有一个
    BrokenVns
        16
    BrokenVns  
       2019-11-28 19:34:11 +08:00
    @gramyang 你的 run()是在 ConnectThread 类里直接重写的吗?
    我见过有人这么写的:
    t = new Thread(()->{
    synchronized (this){...}
    });
    synchronized (t){...}
    上面这种情况就把对象混淆了。
    如果不是我猜的这种情况,你多加点 log 看看,要不试试第 3 条。
    gramyang
        17
    gramyang  
    OP
       2019-11-29 07:33:02 +08:00
    @BrokenVns 不是这样的,是在 ConnectThread 里面调用的 this
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2609 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 06:19 PVG 14:19 LAX 23:19 JFK 02:19
    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