线程间通信

一、锁池和等待池

1)锁池:存放竞争锁失败的线程;

  假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。
2)等待池: 调用wait()的线程,释放锁之后,将当前线程加入等待池;

  假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁后,进入到了该对象的等待池中。

二、线程间通信

  每个线程都拥有自己独立的栈空间,从线程被启动到终止,如果每个运行中的线程都是独立的运行那只能带来很少的价值,我们需要多个线程彼此之间相互协作的来完成工作,我们可以用通知/等待机制来实现线程间通信。

三、等待/通知机制

  等待和通知的相关方法是任意Java对象都具备的,这些方法被定义在所有方法的超类java.lang.Object上;

方法名称描述
wait()调用该方法的线程进入WAITING状态,只有等待另外线程的通知或被中断才会返回,需要注意,调用wait()后,会释放对象的锁
wait(long)超时等待一段时间,这里的参数是毫秒,也就是等待长达n毫秒,如果没有通知就超时返回
wait(long,int)对于超时时间更细粒度的控制,可以达到纳秒
notify()通知任意一个在该对象上等待的线程,使其从wait()方法返回,而返回的潜艇是该线程获取到了对象的锁
notifyAll()通知所有等待在该对象上的线程

 等待/通知机制是指一个线程A调用了对象o的wait()方法进入等待状态,而另一个线程B调用了对象o的notify()或者notifyAll()方法,线程A收到通知后从对象o的wait()方法返回,进而执行后续操作。
  上述两个线程通过对象o来完成交互,而对象上的wait()和notify/notifyAll()的关系就如同开关信号一样,用来完成等待方和通知方之间的交互工作。

1、注意:

  • 调用wait()和notify()的必须是一个对象,调用wait()的对象和加锁对象也必须是同一个对象,否则会抛出异常;

  • wait()、notify()和notifyAll()必须要在锁中使用,即使用时需要先对调用对象o加锁;

  • 调用wait()后,当前线程会释放锁,使其他线程能够继续获取锁使用,当前线程状态由RUNNING变为WAITING,并将当前线程放置到对象的等待队列;

  • notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或notifAll()的线程释放锁之后,等待线程才有机会从wait()返回;

  • notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而notifyAll()方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由WAITING变为BLOCKED;

  • 从wait()方法返回的前提是获得了调用对象的锁;

2、从上述细节中可以看到,等待/通知机制依托于同步机制,其目的就是确保等待线程从
wait()方法返回时能够感知到通知线程对变量做出的修改;

在这里插入图片描述
  上面的图中,WaitThread首先获取了对象的锁,然后调用对象的wait()方法,从而放弃了锁并进入了对象的等待队列WaitQueue中,进入等待状态。由于WaitThread释放了对象的锁,NotifyThread随后获取了对象的锁,并调用对象的notify()方法,将WaitThread从WaitQueue移到SynchronizedQueue中,此时WaitThread的状态变为阻塞状态。NotifyThread释放了锁之后,WaitThread再次获取到锁并从wait()方法返回继续执行。

3、等待/通知的经典范式

该范式分为两部分,分别针对等待方(消费者)和通知方(生产者)。

1)等待方遵循如下原则。

  • 获取对象的锁。
  • 如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
  • 条件满足则执行对应的逻辑。

对应的伪代码如下:

synchronized(o) {
	while(条件不满足) {
		o.wait();
	}
	//对应的处理逻辑
}

2)通知方遵循如下原则。

  • 获得对象的锁。
  • 改变条件。
  • 通知所有等待在对象上的线程。

对应的伪代码如下。

synchronized(o) {
	//改变条件
	o.notifyAll();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值