syncOnce的Go语言与C++11实现方法

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

          Go语言中的sync.Once,用于实现"只执行一次"的功能。功能与pthread_once()差不多。
但pthread_once()可不通用,不过现在C++11终于有了std::call_once来实现这一功能。

虽然一个面向协程,一个面向线程,但这个点要实现的功能是一样的,把两种语言的实现记录一下。  

       在   http://www.cplusplus.com/reference/mutex/call_once/ 有C++11的相关例子,但用了很多新特性。

简化下,便于做对比.

   没有传任何参数的 C++/Go例 子: 

// call_once example
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <mutex>          // std::call_once, std::once_flag

std::once_flag flag;
int Gid = 0;

void setup()
{
	Gid++;
	std::cout << "Called once " << Gid << std::endl;
}


void doprint()
{	
	std::call_once(flag, setup);
}

int main()
{
	std::thread t1(doprint);
	std::thread t2(doprint);
	std::thread t3(doprint);
	std::thread t4(doprint);

	t1.join();
	t2.join();
	t3.join();
	t4.join();

	std::cout << "Gid: " << Gid << std::endl;
}
   

  Go例子:

package main

import (
	"fmt"
	"sync"
	"time"
)

var once sync.Once
var Gid int

func setup() {
	Gid++
	fmt.Println("Called once")
}

func doprint() {
	once.Do(setup)
	fmt.Println("doprint()...")
}

func main() {

	go doprint()
	go doprint()
	go doprint()
	go doprint()

	time.Sleep(time.Second)
	fmt.Println("Gid:", Gid)
}

    关于参数传递,C++是很容易解决的,直接在call_once后面加就行了 。

// call_once example
#include <iostream>       // std::cout
#include <thread>         // std::thread, std::this_thread::sleep_for
#include <mutex>          // std::call_once, std::once_flag

std::once_flag flag;
int Gid = 0;

void setup(std::string parm)
{
	Gid++;
	std::cout << "Called once! " << Gid << " parm:" << parm.c_str() << std::endl;
}

void doprint(std::string parm)
{	
	std::call_once(flag, setup, parm);
}

int main()
{
	std::thread t1(doprint, "1");
	std::thread t2(doprint, "2");
	std::thread t3(doprint, "3");
	std::thread t4(doprint, "4");

	t1.join();
	t2.join();
	t3.join();
	t4.join();

	std::cout << "Gid: " << Gid << std::endl;
}
        Go语言的sync.Once后面不允许直接传参数,但可以通过以下方法来变通。

package main

import (
	"fmt"
	"sync"
	"time"
)

var once sync.Once
var Gid int

func doprint(parm string) {
	setup := func() {
		Gid++
		fmt.Println("Called once! parm:", parm)
	}
	once.Do(setup)
	fmt.Println("doprint()...")
}

func main() {

	go doprint("1")
	go doprint("2")
	go doprint("3")
	go doprint("4")

	time.Sleep(time.Second)
	fmt.Println("Gid:", Gid)
}

   完毕!



MAIL: xcl_168@aliyun.com

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





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

本文来自:CSDN博客

感谢作者:xcltapestry

查看原文:syncOnce的Go语言与C++11实现方法

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

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