Linux--pthread_once 的用法

pthread_once 一般用于一次性的线程初始化,在整个声明周期中,该方法只执行一次,从而实现一种线程安全的单例模式。


Pthread_once () 函数语法要点
头文件 : #include

函数原型 : int pthread_once(pthread_once_t *once_control, void(*int_routine)(void));

once_control : 一个静态或全局变量,初始化为 PTHREAD_ONCE_INT

init_routine : 初始化函数的函数指针

返回值:成功: 0   错误:错误码

LinuxThreads使用互斥锁和条件变量保证由pthread_once()指定的函数执行且仅执行一次,而once_control则表征是否执 行过。如果once_control的初值不是PTHREAD_ONCE_INIT(LinuxThreads定义为0),pthread_once() 的行为就会不正常。在LinuxThreads中,实际"一次性函数"的执行状态有三种:NEVER(0)、IN_PROGRESS(1)、DONE (2),如果once初值设为1,则由于所有pthread_once()都必须等待其中一个激发"已执行一次"信号,因此所有pthread_once ()都会陷入永久的等待中;如果设为2,则表示该函数已执行过一次,从而所有pthread_once()都会立即返回0。

[root@localhost 06]# cat pthread3.cpp
#include
#include
using namespace std;

pthread_once_t once = PTHREAD_ONCE_INIT;

void once_run(void)
{
        cout<<"once_run in thread "<<(unsigned int )pthread_self()< }

void * child1(void * arg)
{
        pthread_t tid =pthread_self();
        cout<<"thread "<<(unsigned int )tid<<" enter"<         pthread_once(&once,once_run);
        cout<<"thread "< }


void * child2(void * arg)
{
        pthread_t tid =pthread_self();
        cout<<"thread "<<(unsigned int )tid<<" enter"<         pthread_once(&once,once_run);
        cout<<"thread "< }

int main(void)
{
        pthread_t tid1,tid2;
        cout<<"hello"<         pthread_create(&tid1,NULL,child1,NULL);
        pthread_create(&tid2,NULL,child2,NULL);
        sleep(10);
        cout<<"main thread exit"<         return 0;

}
[root@localhost 06]# g++ -lpthread pthread3.cpp -o pthread3
[root@localhost 06]# ./pthread3
hello
thread 3086535584 enter
once_run in thread 3086535584
thread 3086535584 return
thread 3076045728 enter
thread 3076045728 return

例子:muduo 网络库的 Singleton 就用到了 pthread_once。 

template
class Singleton : boost::nocopyable{
public:
    static T& instance(){
        pthread_once(&ponce_,&Singleton::init);         // 保证ponce_只会被执回调执行一次Singleton::init
        return *value_;
    }
private:
    Singleton();
    ~Singleton();
    static void init(){
        value_ = new T();
    }
private:
    static pthread_once_t ponce_;
    static T* value_;
};

// 必须在头文件中定义static 变量

template
pthread_once_t Singleton::ponce_ = PTHREAD_ONCE_INIT;
template
T* Singleton::value_ = NULL;

注意事项
在使用 pthread_once () 函数时需要注意,不能在其回调函数中调用 fork (),否则,当再次调用 pthread_once () 时,会在子进程中导致死锁。而且,不能在回调函数中抛出一个 C++异常。 

你可能感兴趣的:(C++,C,工作笔记,linux,centos,ubuntu,网络)