Java:阻塞态和等待态线程对锁的竞争

1. 阻塞态线程

注意,区分阻塞线程获得了锁,和唤醒一个阻塞的线程。

JVM会在锁释放的时候,唤醒被阻塞的线程。阻塞线程获得了锁,就直接进入就绪态。

当一个线程持有的锁被释放后,JVM会自动唤醒阻塞在该锁上的其他线程。唤醒过程如下:

  • 持有锁的线程释放锁。
  • JVM会从阻塞队列中选择一个等待该锁的线程,将其从阻塞态转为就绪态。
  • 该线程进入就绪态后,开始竞争CPU时间片,操作系统调度其中一个线程执行。
  • 竞争到CPU时间片的线程会尝试获取锁。如果成功,它将进入运行态,执行同步代码块或同步方法。

在这个过程中,阻塞态的线程并不需要显式的notify()来唤醒,因为锁的释放是自动管理的。notify只会唤醒等待态的线程,而不会唤醒阻塞态的线程。

2. 等待态线程

        对于等待态的线程,需要使用notify唤醒,被唤醒的锁也不会直接获得锁,而是进入就绪态,然后进入竞争锁的过程。如果没有竞争成功,那么转入阻塞态。

        首先,wait()、notify()方法是针对对象的,调用任意对象的 wait()方法都将导致线程等待,等待的同时也将释放该对象的锁,相应地,调用任意对象的 notify()方法则将随机解除因该对象wait而进入等待态的线程,但它需要重新获取该对象的锁(注意notify并不是把锁给一个正在阻塞的线程,而是把一个线程从阻塞队列转到竞争队列,也就是阻塞态转为就绪态,等待CPU调度执行),直到获取成功才能往下执行;

        其次,wait、notify 方法必须在 synchronized 块或方法中被调用,并且要保证同步块或方法的锁对象与调用wait、notify 方法的对象是同一个,如此一来在调用 wait 之前当前线程就已经成功获取某对象的锁,执行 wait 阻塞后当前线程就将之前获取的对象锁释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值