notify和notifyAll坑点

1.前言

优化Application时,由于上报uv和pv的操作初始需要读取配置和加载so库很多io操作,相对非常耗时,所以参考SharedPerfencesImpl的实现做了延迟加载,如果发现需要使用但是为初始完成会让调用线程wait.所以初始化结束时需要调用notifyall.

2. 问题

代码示例

public class Demo{
        public void init(){
            new Thread(){
                public void run() {
                      synchronized (Demo.this) {
                          //io操作
                          //初始化赋值操作
                          notifyAll();
                  }
                }
        }
}

在上面的同步块中直接调用notifyAll();这里会产生错误:

IllegalMonitorStateException: object not locked by thread before notify

当时一直不明白为何会产生这个错误,后面这么修改:

synchronized(this){
    notifyAll();
 }

当时没有报错,而且用户数据也上报成功,也就没有细节去分析.现在回头来看,突然发现这里的调用并不是正确的.正确的调用应该是

Demo.this.notifyAll();

public class Demo{
        public void init(){
            new Thread(){
                public void run() {
                      synchronized (Demo.this) {
                     loadInit();
                  }
                }
        }
        private void loadInit(){
             //io操作
            //初始化赋值操作
            notifyAll();
        }
}

3.原因

notifyall需要在同步块中,所以需要去获取当前对象的锁,而第一次直接调用是表示Thread.this.notifyAll();但是并没有去获取线程的锁.而加了synchronized(this){}不会报错了,是因为获取了Thread对象的锁,但是没有线程因为Thread对象wait.所以不是我们需要的效果.而后面的两种解决方案的实质是一样的.都是调用Demo.this对象的notifyall,但是后民使用方法替代,而没有使用Demo.this.notifyall的原因是,线程内部类隐式持有外部引用,而loadInit方法是外部Demo的方法,所以调用的时候是Demo.this.loadInit();所以执行notifyall的操作对象是Demo.this,而不是Thread.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值