生产者/消费者模型
有了信号量这个利器,我们就可以处理比较复杂的线程同步模型了。
首先,我们来看一个比较简单的生产者/消费者模型。还是以Java代码为例。
public static final Object signal = new Object();
public static final char[] buf = new char[1024]; // 需要同步访问的共享资源
// 生产者代码
… produce() {
for(… ) { // 循环执行
synchronized(signal){
// 产生一些东西,放到 buf 共享资源中
signal.notify(); //然后通知消费者
signal.wait(); // 然后自己进入signal待召队列
}
}
}
// 消费者代码
… consume() {
for(… ) { // 循环执行
synchronized(signal){
signal.wait(); // 进入signal待召队列,等待生产者的通知
// 读取buf 共享资源里面的东西
signal.notify(); // 然后通知生产者
}
}
}
上述的生产者/消费者模型的实现非常简单,只用了一个信号量signal。这只是一段示意代码。
实际上的生产者/消费者模型的实现可能非常复杂。可以引入buf已满或者已空的判断,可以引入更多的信号量,也可以引入一个环状的buf链。但那些都是性能优化方面的工作,基本的信号量工作方式还是不变的。
生产者/消费者模型是典型的Coroutine。而且,当消费者或者生产者线程进入待召队列的时候,当前的运行栈状态就暂时保存在系统当中,这种状况又是典型的Continuation。
因此,我们完全可以用信号量机制自己实现Coroutine和Continuation。其实,那些在语法层面上支持Coroutine和Continuation的语言,内部实现原理也是采用类似的信号量同步机制。
有了信号量这个利器,我们就可以处理比较复杂的线程同步模型了。
首先,我们来看一个比较简单的生产者/消费者模型。还是以Java代码为例。
public static final Object signal = new Object();
public static final char[] buf = new char[1024]; // 需要同步访问的共享资源
// 生产者代码
… produce() {
for(… ) { // 循环执行
synchronized(signal){
// 产生一些东西,放到 buf 共享资源中
signal.notify(); //然后通知消费者
signal.wait(); // 然后自己进入signal待召队列
}
}
}
// 消费者代码
… consume() {
for(… ) { // 循环执行
synchronized(signal){
signal.wait(); // 进入signal待召队列,等待生产者的通知
// 读取buf 共享资源里面的东西
signal.notify(); // 然后通知生产者
}
}
}
上述的生产者/消费者模型的实现非常简单,只用了一个信号量signal。这只是一段示意代码。
实际上的生产者/消费者模型的实现可能非常复杂。可以引入buf已满或者已空的判断,可以引入更多的信号量,也可以引入一个环状的buf链。但那些都是性能优化方面的工作,基本的信号量工作方式还是不变的。
生产者/消费者模型是典型的Coroutine。而且,当消费者或者生产者线程进入待召队列的时候,当前的运行栈状态就暂时保存在系统当中,这种状况又是典型的Continuation。
因此,我们完全可以用信号量机制自己实现Coroutine和Continuation。其实,那些在语法层面上支持Coroutine和Continuation的语言,内部实现原理也是采用类似的信号量同步机制。