无法进入临界区的时候选择阻塞而不是忙等待。有sleep和wakeup两个方法。
信号量semaphore
up和down两种操作。down做减一操作,如果信号量大于0就减一,不然就睡眠线程。关键在于原子操作,所以一般是在系统层面的。
首先两个进程同时运行。当A进程想进入临界区的时候执行down操作来做标记,把一般信号量和mutex(互斥锁)都down一遍,这个时候如果信号量小于等于0,则其他进程没办法再进入临界区(会被系统方法阻塞)直至信号量重新大于零。这种就可以解决生产者-消费者模型了,可以保证仓库里的货物一定是大于零的,可以被消费的,而mutex信号量则用来锁住仓库。
互斥量mutex
条件变量condition
考虑生产者消费者模型,当仓库满的时候生产者需要阻塞。当仓库又有空位的时候需要有人告诉生产者脱离阻塞,这就是条件变量要做的事。
管程monitor
在java中就是sychronized块,只能由某个线程执行。
==============================================Java================================================
Java中的同步
首先了解notify和wait。这两个是Object的方法,不属于Thread。
在一个while true循环里使用这个。当不符合条件的时候,使用wait来让所有使用该object的线程阻塞,当符合条件的时候,使用notifyAll来放行。
在sychronized块里面使用wait以及notify,否则虚拟机会生成IllegalMonitorStateException。
Java中的中断
stop方法已经废弃,强制退出容易引起各种状态问题。由于线程不同于进程,采取的是协作机制,而非竞争机制,所以采用更加和平的“通知”方式。当用户想要停止某个线程的时候,就会向它发一个interrupt()方法,这个方法会设置Thread里面的标识位。这个线程会在合适的时机调用isInterrupted()来判断标志位,并在自己觉得可以的时候退出(在这之前做一些手尾工作,回退状态,回退操作etc.)(当然它也可以无视这个标识位)。
退出的方式是抛出一个InterruptedException。
public static boolean interrupted 一个静态方法,由线程调用的时候会检测当前线程是否被中断标识,并且清除中断位。
=====================================================Java=====================================================
消息传递
ab线程都在loop中。当a觉得b可以处理事情的时候,发送一条消息给b,b随即从loop中拿到消息并开始处理事情。
屏障 barrier
只有当所有进程都到达某个条件的时候,才开放屏障,所有线程允许进入下一个阶段。