[android]同步块代码中wait和sleep方法持有锁状态的区别

需求

最近项目中这么一个功能,希望app监听android file system,当有文件create/modify/detele时,app收到通知,把对应的变化信息告诉服务器


需求的解决方案

当我们用手机拍照时,会把拍照的文件保存在sdcard的DCIM文件夹下。当文件生成时,我们会接收到create/modify/write_close消息,我们要做的是在write_close之后,再发送消息给服务器,这样一来,当我们收到create消息时,就需要把当前线程阻塞住,直到收到write_close消息之后再调用notifyAll来开启阻塞的线程。


问题

问题出在:我们在接收到write_close消息之后,虽然调用了setState(true),但是isChange的值并没有马上改变,而是过了好几秒之后才被改变


来看看核心代码

while (count > 0) {  //阻塞线程的代码,一下代码简称:循环
				
				synchronized (this) {
					if (!isChange) { //当isChange不变为true时,一直等待,直到接收到write_close消息,调用setState(true)
						try {
							Log.d(LOG_TAG, "sleeping ......");
							this.wait(1000);  //这里原先调用的是TimeUnit.MILLISECONDS.sleep(1000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						continue;
					}
				}

				//...省略代码sendMsg2Server();结束后break
			}

public synchronized void setState(boolean isChange){
			this.isChange = true;
			this.notifyAll();//原来是没有加这句,在改成wait(1000)之后,调用notifyAll()
		}


问题解决方案

把TimeUnit.MILLISECONDS.sleep(1000)改成wait(1000),并且在setState(true)里notifyAll()。


问题的根源

在if(!isChange)和setState()里都用了同步块,同步锁是this。当我们调用sleep(1000)时,循环并没有交出同步锁,而是持有锁直到1秒sleep完成,代码走到continue,这时重新进入while循环,进入同步块,这时setState()和循环会竞争这个this锁,setState()没有竞争到这个锁是很正常的,只要setState()没有竞争到锁,循环就会sleep 1秒,这样就会造成打印了好几句Log.d(LOG_TAG, "sleeping ......");之后才改变isChange的值的情况。


当我们把代码改成wait(1000)之后,循环马上把锁交了出去,setState()拿到锁,马上改变isChange的值,并且通知循环,这样就能进入后面sendMsg2Server()的代码了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值