在Go语言中 sync.Cond 代表条件变量,但它需要配置锁才能有用.
var m Mutex
c := NewCond(&m)
或 c := sync.NewCond(&sync.RWMutex{}) 之类. 它有三个函数: wait/signal/broadcast 望文知义,和Windows下的InitializeConditionVariable与WaitForSingleObject()之类, 及Linux下的pthread_cond_t等作用差不多.
弄了两个例子:
/*
条件变量 Cond 例子
Author: xcl
Date: 2015-11-29
*/
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
func main() {
runtime.GOMAXPROCS(4)
test333()
}
func testCond() {
c := sync.NewCond(&sync.Mutex{})
condition := false
go func() {
time.Sleep(time.Second * 1)
c.L.Lock()
fmt.Println("[1] 变更condition状态,并发出变更通知.")
condition = true
c.Signal() //c.Broadcast()
fmt.Println("[1] 继续后续处理.")
c.L.Unlock()
}()
c.L.Lock()
fmt.Println("[2] condition..........1")
for !condition {
fmt.Println("[2] condition..........2")
//等待Cond消息通知
c.Wait()
fmt.Println("[2] condition..........3")
}
fmt.Println("[2] condition..........4")
c.L.Unlock()
fmt.Println("main end...")
}
/*
testCond()运行结果:
[2] condition..........1
[2] condition..........2
[1] 变更condition状态,并发出变更通知.
[1] 继续后续处理.
[2] condition..........3
[2] condition..........4
main end...
*/
复制代码
例二
/*
条件变量 Cond 例子
Author: xcl
Date: 2015-11-29
*/
package main
import (
"fmt"
"runtime"
"sync"
"time"
)
const MAX_CLIENTS = 3
func main() {
runtime.GOMAXPROCS(4)
testCond()
}
func testCond() {
s := NewServer()
go s.IOloop()
time.Sleep(time.Second * 1)
go func() {
s.Release()
}()
go func() {
s.Release()
}()
time.Sleep(time.Second * 1)
s.Release()
time.Sleep(time.Second * 1)
fmt.Println("[testCond] end.")
}
type Server struct {
clients uint64
cond *sync.Cond
}
func NewServer() *Server {
s := &Server{}
s.cond = sync.NewCond(&sync.Mutex{})
return s
}
func (s *Server) IOloop() {
for {
s.cond.L.Lock()
for s.clients == MAX_CLIENTS {
fmt.Println("[IOloop] 等于MAX_CLIENTS了,等待Cond通知.即有触发Release()")
s.cond.Wait()
}
s.cond.L.Unlock()
s.clients++
fmt.Println("[IOloop] clients:", s.clients)
}
}
func (s *Server) Release() {
s.cond.L.Lock()
s.clients--
fmt.Println("[Release] a clients:", s.clients)
s.cond.Signal()
fmt.Println("[Release] b clients:", s.clients)
s.cond.L.Unlock()
}
/*
运行结果:
[IOloop] clients: 1
[IOloop] clients: 2
[IOloop] clients: 3
[IOloop] 等于MAX_CLIENTS了,等待Cond通知.即有触发Release()
[Release] a clients: 2
[Release] b clients: 2
[Release] a clients: 1
[Release] b clients: 1
[IOloop] clients: 2
[IOloop] clients: 3
[IOloop] 等于MAX_CLIENTS了,等待Cond通知.即有触发Release()
[Release] a clients: 2
[Release] b clients: 2
[IOloop] clients: 3
[IOloop] 等于MAX_CLIENTS了,等待Cond通知.即有触发Release()
[testCond] end.
*/
对于条件变量和channl,知乎有个问答很精彩,可以看看: http://www.zhihu.com/question/27256570
另外 <<Go语言并发编程>>中也有个同一时间多个Goroutine分别进行对一个文件进行读写操作的例子也很精彩,直观。
噢,对了,附上C++11条件变量的使用例子:
// condition_variable example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id (int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
// ...
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
}
int main ()
{
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i)
threads[i] = std::thread(print_id,i);
std::cout << "10 threads ready to race...\n";
go(); // go!
for (auto& th : threads) th.join();
return 0;
}