java 多线程 synchronized与Object类中wait、notify、notifyAll方法的使用

synchronized的使用:

(1)synchronized(obj){}的使用

obj是一个实例对象,可以是任意对象,当在多线程中通过各种方式执行到该synchronized包围的代码段,需要先拿到obj对象的锁才能继续往后执行,否则就阻塞,阻塞的时候一直判断有没有拿到obj的锁,如果拿到obj的锁了,就可以继续执行,如果还没拿到obj的锁,继续阻塞。

(2)synchronized用在实例方法(或者叫做动态方法)上

相当于(1)中所说的

synchronized(this){

     //实例方法的代码放在这...

}

(3)synchronized用在静态方法上

假设该静态方法属于A类,则相当于(1)中所说的

 

synchronized(A.class){

     静态方法的代码放在这...

}

Object中wait、notify、notifyAll方法的使用

正常使用这三个方法的前提:这三个方法的使用必须在同步代码块中,并且该同步代码块的对象锁是这几个方法所属的对象的对象锁。否则报非法监视器异常(IllegalMonitorStateException)。具体看下面代码:

//下面synchronized的参数如果是lock对象,则在该同步代码块内只能调用lock对象的wait、notify、notifyAll方法
        synchronized (lock) {
            try {
                lock.wait();
                // lock.notify();
                // lock.notifyAll();
            } catch (InterruptedException e) {
                // TODO 自动生成的 catch 块
                e.printStackTrace();
            }
        }

为什么要这样呢?因为释放锁与获得的锁都要是同一个锁才能保证同步。

synchronized一开始是获得lock对象的锁,那么只有调用lock对象的wait方法才能保证这个时候wait方法释放的是同一把锁。

用反例来说明:

首先,wait方法的作用是释放对象锁,然后阻塞当前线程(也就是当前线程跑到阻塞队列中了)。

当调用的是其他对象的wait方法时,不会释放lock的对象锁,而当前线程却又跑到阻塞队列中了,那么lock对象锁还是一直被当前线程把持着----------也就是说,当前线程被阻塞了,却还持有lock的对象锁,这就会导致其它线程无法再获得lock的对象锁,然后导致死锁。

1、wait的使用

   前面的例子中其实就是用wait作为讲解,这里不再赘述。

2.notify的使用

唤醒该notify()方法所属对象的等待集中随机一个线程,被唤醒的线程处于可运行状态,即此时该线程可以和其他线程一起竞争锁了。

但是,需要注意,调用notify时,所属同步代码块是不会立即释放锁的,而是在该代码块执行完之后释放锁,也就是说,被唤醒的线程还是要等当前调用notify的线程中的同步代码块执行完才能开始竞争,否则只能等着。不懂的话,看下面的截图

3.notifyAll的使用

与notify类似,只不过是唤醒该notifyAll方法所属对象的等待集中的所有线程,其他就与notify一样了。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值