Go语言条件变量的两个例子

xcltapestry · · 4962 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

在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;
}
C++11例子来自: http://www.cplusplus.com/reference/condition_variable/condition_variable/

BLOG: http://blog.csdn.net/xcl168



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:xcltapestry

查看原文:Go语言条件变量的两个例子

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4962 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传