【Go 语言社区】Go语言条件变量的两个例子

在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;

}

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2016-02-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

IDEA Intellij小技巧和插件

使用IDEA Intellij已有两年,在此罗列一下在实践中觉得能有效提升开发效率的一些小技巧和插件。  1. 重设移动键 方向键和Home/End键离...

3981
来自专栏菩提树下的杨过

Flash/Flex学习笔记(4):如何打开网页及Get/Post数据

flash终究只是客户端技术,所以很多时候还是需要与服务端技术(比如asp,asp.net,jsp,php之类)进行数据交互的,下面的代码演示了如何在flash...

2277
来自专栏智能大石头

手工调试自定义控件各主要方法执行顺序(分运行时和设计时)

继承TextBox,override各个方法,分别下断点调试。 ctor为构造函数 在构造函数中,通过代码: this.Text = (new Random(D...

20910
来自专栏技术墨客

React学习(最终篇)—— 高阶应用:高阶组件(HOCs)

高阶组件(higher-order components:以下简称HOC或HOC组件)是一个React组件复用的高级技巧。HOCs本身并不是React的API接...

2554
来自专栏Java学习网

Chrome开发者工具的小技巧

 Chrome的开发者工具是个很强大的东西,相信程序员们都不会陌生,不过有些小功能可能并不为大众所知,所以,写下这篇文章罗列一下可能你所不知道的功能,有的功能可...

4124
来自专栏老马寒门IT

jQuery EasyUI 详解

easyui 为创建现代化,互动,JavaScript 应用程序,提供必要的功能。

4061
来自专栏IMWeb前端团队

react组件性能优化探索实践

React本身就非常关注性能,其提供的虚拟DOM搭配上Diff算法,实现对DOM操作最小粒度的改变也是非常的高效。然而其组件渲染机制,也决定了在对组件进行更新时...

2527
来自专栏.NET开发者社区

C#Winform使用扩展方法自定义富文本框(RichTextBox)字体颜色

在利用C#开发Winform应用程序的时候,我们有可能使用RichTextBox来实现实时显示应用程序日志的功能,日志又分为:一般消息,警告提示 和错误等类别。...

2916
来自专栏向治洪

ios开发之xcode环境介绍

作为一个刚入门ios开发的人来说,对于ios开发,对于xcode一切都是那么的陌生,那么我们如何开始我们的第一步呢?首先对开发的ide是必须要了解的,其实要对开...

2656
来自专栏Ryan Miao

照着官方文档学习react

准备 先要准备环境。搭建一个基于webpack的react环境:Hello ReactJS. 一些要点 我在想是否应该完整的记录照抄的过程呢。毕竟已经开始一段,...

3587

扫码关注云+社区

领取腾讯云代金券