11.5.3 同步线程的设计方法

11.5.3 同步线程的设计方法

前面讨论了线程间的互斥。还有一种线程间对共享数据的相互影响,是一个线程的运行要依赖于另一个线程对共享数据的处理结果,这称为线程间的同步。

线程同步的设计方法是,除了加互斥锁外,还要在并行运行的线程上加信号量。信号量是一个标志,表示一种操作(如生产和销售)是否已执行完,另一操作(如销售或生产)是否可以执行了。

Object类提供了一组关于线程同步的方法——wait()方法和notify()方法。

• void wait()

引起当前线程等待,直到另一个线程调用notify()方法或notifyAll()方法。

• void wait(long time)

引起当前线程等待,直到另一个线程调用notify()方法或notifyAll()方法。或者等待的时间time到。

• void notify()

唤醒一个正在等待这个对象的线程。

• void notifyAll()

唤醒所有正在等待这个对象的线程。

wait()方法的所谓等待,是把当前线程从运行状态转为阻塞状态;notify()方法的所谓唤醒是把等待线程从阻塞状态转为可运行状态,从而有机会让线程调度程序调度进入运行状态。

注意:wait()方法所在的代码段一定要加互斥锁synchronized。因为:wait()方法在把当前线程从运行状态转为阻塞状态后,还要释放互斥锁锁定的共享资源(否则其他同步线程无法运行),这样的操作不允许中间被打断,这显然是共享资源的互斥问题。因此,wait()方法所在的代码段一定要加互斥锁synchronized。

【例11-7】计算机模拟生产——销售问题。

要求:为了简化生产——销售问题,规定仓库中一次可存放若干数量的货物,但必须满足:仓库中一旦有货就一次销售完;仓库中一旦无货就一次完成本次生产。

设计思路:通过分析本例问题,需要设计四个类:仓库类、生产类、销售类和测试类。

程序代码如下:

1.仓库类

img483

img484

img485

2.生产类

img486

img487

3.销售类

img488

4.测试类

img489

img490

程序运行结果如下:

img491

pub goods=15      get goods=15

从运行结果可以看出,完全达到题目要求的满足生产和销售同步的设计要求。

【程序说明】

1)信号量available的作用是控制线程的同步操作;

2)在Storage类的put()和get()方法定义中使用了synchronized互斥锁;

3)在Storage类的put()和get()方法中调用wait()方法和notify()方法。wait()方法和notify()方法是配对的一组方法。程序中当判断信号量不满足要求时调用wait()方法,则使当前线程从运行状态转入阻塞状态,并释放当前运行线程互斥锁锁定的共享资源—对象com;当判断信号满足要求时,执行完方法(put()和get()方法)要求的语句后,调用notify()方法,唤醒一个正等待这个共享资源—对象com的线程。