這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
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_flagstd::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 mainimport ("fmt""sync""time")var once sync.Oncevar Gid intfunc 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_flagstd::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 mainimport ("fmt""sync""time")var once sync.Oncevar Gid intfunc 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