Android synchronized wait notify 多线程同步

来源:互联网 发布:过期域名删除时间查询 编辑:程序博客网 时间:2024/05/17 03:03

项目中碰到问题,涉及到主线程和子线程的通信和同步问题,测试中发现死锁情况,记录一下

 void Main(){

    ThreadB Threadb = new ThreadB();
    
Threadb .start();
    synchronized (handler) {
       try {
                Log.e("sync_ThreadManager", "hold_Handeler");    
                handler.wait();
                Log.e("sync_ThreadManager", "wait_Handeler");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

 }

ThreadB extends Thread

{

    public void run() {
        Looper.prepare();
        bHandler = new Handler() {
            @Override

            public void handleMessage(Message msg) {
             //do something here
            }
        };
        synchronized (handler) {
            handler.notify();
        }
        Looper.loop();
    }

}

上述代码设计意图是:红色代码执行的时候,启动另外一个线程,主线程先执行到蓝色部分(wait),此时,wait函数会导致主线程处于suspend状态,并且释放所hold的同步对象锁handler。此后子线程threadb获得同步锁handler,threadb初始化完毕,调用notify方法通知调用wait的线程,然后主线程会重新请求同步锁,如果成功则继续执行wait后面的代码,这个过程确保了子线程threadb的bhandler成功初始化,以后主线程main可以通过bhandler和子线程进行通信。大多情况下程序运行正常。但是多线程情况下并不能保证这个顺序,可能出现假死。

正常情况如下:

1.Main 执行到synchronized (handler) ,抢先获得handler锁对象

2.vm切换执行threadb,执行到synchronized (handler)发现handler锁对象已被Main进程hold,此时threadb阻塞等待

3.Main继续执行hanlder.wait(),释放handler锁并等待

4.threadb获得handler锁,初始化bhandler,执行hanlder.notify()

5.Main得到通知,重新请求handler锁,但是此时threadb尚未出同步代码区,没有释放handler锁,Main继续等待,threadb继续执行,释放hanlder

6.Main请求hanlder锁成功,继续执行wait后面的操作

 

threadb先执行:

1.Main执行 Threadb.start() 

2.VM切换执行threadb,获得handler锁。

3.VM切换执行Main,发现hanlder锁被threadb hold,阻塞等待

4.VM切换threadb,继续执行notify,直到出同步代码区,释放hanlder锁

5.VM切换执行Main,获得hanlder锁,执行到wait,阻塞等待别的线程notify

6.这个例子中,notify只执行了一次,所以main,再也等不到别的线程叫它吃饭了(notify),只好饿死

主要问题是notify 不能通知到后到来wait线程,所以解决方法就是确保main线程先进入synchronized,可在threadb 执行synchronized之前判断main是否已经进入synchronized

 

 

 

原创粉丝点击