Java中Object.wait()、Object.notify()/notifyAll()底层原理

synchronized与互斥锁mutex

synchronized用来锁定某个对象,体现的是标准的互斥锁mutex的机制,synchronized代码块的开始即是lock该mutex,代码块的结束即是unlock。

Object.wait()与条件变量

Object.wait()在使用时通常要判断是否满足某个条件,不满足某个外部条件cond时调用wait(),来让线程阻塞同时释放被synchronized锁定的mutex;从这个过程看来Object.wait()实际上是起到条件变量的作用,wait()内部实际上先将synchronized锁定的锁释放,之后将当前线程阻塞在某个内置的条件condition上(注意:此condition为内置的,与外部判断的条件cond并非同一个,外部的cond需要程序员根据程序逻辑来判断改变,而这个condition只能被Object.notify()/notifyAll()改变),直到内置条件condition被Object.notify()/notifyAll()修改时才会重新锁定该mutex,继续执行wait()后的代码。

Object.notify()/notifyAll()与条件变量

Object.notify()/notifyAll()实际上只起到一个sinal内置条件变量的作用,调用Object.notify()/notifyAll()之后,这个时候其他处于wait()中的线程所等待的内置条件变量已经满足,但是由于wait()中仍然需要lock mutex,而在Object.notify()/notifyAll()中没有把mutex释放掉,故阻塞在wait()处的线程继续等待,但等待的条件不再是内置条件变量而是锁mutex;直到synchronized代码块结束时,由于会自动释放被synchronized锁定的mutex,故此时所有在wait()中等待mutex的线程开始竞争mutex,得到该mutex的会继续执行,否则继续等待mutex。

相关代码

1
2
3
4
5
6
7
synchronized (obj) { // 此处相当于mutex=obj,lock(mutex)
     while (!cond) { // 判断外部条件cond,不满足时让线程wait();
         obj.wait();
     }
     // .....执行满足条件cond时的逻辑过程
     obj.notifyAll(); // 更改内置条件condition
} // 此处相当于mutex=obj,unlock(mutex)

obj.wait()内部实现(伪代码):

1
2
3
4
5
wait() {
     unlock(mutex); //解锁mutex
     wait_condition(condition); //等待内置条件变量condition
     lock(mutex); //竞争锁
}

obj.notify()/notifyAll()内部实现(伪代码):

1
2
3
obj.notify()/notifyAll(){
     condition= true ; //只起到把内置条件变量置为true的作用
}

注意:该代码中之所以用while循环判断该外部条件cond,是因为,第一次Object.notify()/notifyAll()被调用之后,所有线程所等待的内部条件condition都已经满足。此时所有线程竞争mutex,而mutex只会被其中一个线程获得,其余线程继续等待在mutex上。当获得mutex的那个线程执行结束时,所有线程又会竞争mutex,此时,某个线程因为获得了mutex而继续执行。 但这个过程中该线程并没有判断外部条件cond是否成立。 也许在第一次获得mutex的线程中已经将外部条件cond改变为false,而当前获得mutex的线程没有判断cond是否为true而直接执行了后续的代码,相当于通过漏洞执行了后续的代码,必然导致程序逻辑的错误。故,必须用while判断外部条件。同时,由此得出,wait和notify所等待和改变的内置条件变量condition一定在obj对象中,只有这样所有被锁定在obj上的线程才能共享该condition。故可以做这样的推断:
被synchronized锁定的mutex为mutex =obj.mutex;
被wait和notify共享的内置条件变量condition = obj.condition;

总结

在使用synchronized、Object.wait()、Object.notify()/notifyAll()实现线程同步时,用到了两种机制:线程互斥锁mutex和条件变量condition。

转载自:https://blog.csdn.net/achellies/article/details/7094467

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值