zoukankan      html  css  js  c++  java
  • LInux多线程编程----线程特定数据的处理函数

    1、pthread_key_t和pthread_key_create()

        线程中特有的线程存储, Thread Specific Data 。线程存储有什么用了?他是什么意思了?大家都知道,在多线程程序中,所有线程共享程序中的变量。现在有一全局变量,所有线程都可以使用它,改变它的值。而如果每个线程希望能单独拥有它,那么就需要使用线程存储了。表面上看起来这是一个全局变量,所有线程都可以使用它,而它的值在每一个线程中又是单独存储的。这就是线程存储的意义。
       线程存储的具体用法:

     (1)创建一个类型为 pthread_key_t 类型的变量。

     (2)调用 pthread_key_create() 来创建该变量。该函数有两个参数,第一个参数就是上面声明的 pthread_key_t 变量,第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。

     (3)当线程中需要存储特殊值的时候,可以调用 pthread_setspcific() 。该函数有两个参数,第一个为前面声明的 pthread_key_t 变量,第二个为 void* 变量,这样你可以存储任何类型的值。

     (4)如果需要取出所存储的值,调用 pthread_getspecific() 。该函数的参数为前面提到的 pthread_key_t 变量,该函数返回 void * 类型的值。

    2、pthread_once 和 pthread_key

        一次性初始化

        有时候我们需要对一些posix变量只进行一次初始化,如线程键(我下面会讲到)。如果我们进行多次初始化程序就会出现错误。

        在传统的顺序编程中,一次性初始化经常通过使用布尔变量来管理。控制变量被静态初始化为0,而任何依赖于初始化的代码都能测试该变量。如果变量值仍然为0,则它能实行初始化,然后将变量置为1。以后检查的代码将跳过初始化。

        但是在多线程程序设计中,事情就变的复杂的多。如果多个线程并发地执行初始化序列代码,可能有2个线程发现控制变量为0,并且都实行初始化,而该过程本该仅仅执行一次。

       如果我们需要对一个posix变量静态的初始化,可使用的方法是用一个互斥量对该变量的初始话进行控制。但有时候我们需要对该变量进行动态初始化,pthread_once就会方便的多。 

       有些事需要一次且仅需要一次执行。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread_once_t)会比较容易些。

    3、示例代码及运行结果:

    /*
     * ThreadSpecificData.c
     *
     *  Created on: Aug 11, 2013
     *      Author: root
     */
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    
    #if 0
    char * str_accumulate(char *s){
        static char accu[1024] = {0};
        strcat(accu, s);
        return accu;
    }
    #endif
    
    static pthread_key_t str_key;
    static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
    static void str_alloc_key();
    static void str_alloc_destroy_accu(void * accu);
    char * str_accumulate(const char *s){
        char * accu;
        pthread_once(&str_alloc_key_once, str_alloc_key);
        accu = (char*)pthread_getspecific(str_key);
        if(accu == NULL){
            accu = malloc(1024);
            if(accu == NULL) return NULL;
            accu[0] = 0;
            pthread_setspecific(str_key, (void*)accu);
            printf("Thread %lx:allocating buffer at %p
    ", pthread_self(), accu);
        }
        strcat(accu, s);
        return accu;
    }
    
    static void str_alloc_key(){
        pthread_key_create(&str_key, str_alloc_destroy_accu);
        printf("Thread %lx:allocated key %d
    ", pthread_self(), str_key);
    }
    
    //thread specific data is NULL, this function will be called by this thread.
    static void str_alloc_destroy_accu(void *accu){
        printf("Thread %lx:freeing buffer at %p
    ", pthread_self(), accu);
        free(accu);
    }
    void * process(void * arg){
        char * str;
        str = str_accumulate("Result of ");
        str = str_accumulate((char*)arg);
        str = str_accumulate(" thread");
        printf("Thread %lx:"%s"
    ", pthread_self(), str);
        return NULL;
    }
    
    int main(){
        char * str;
        pthread_t th1,th2;
        str = str_accumulate("Main process Result of");
        pthread_create(&th1, NULL, process, (char*)"first");
        pthread_create(&th2, NULL, process, (char*)"second");
        str = str_accumulate("initial thread");
        printf("Thread %lx:"%s"
    ", pthread_self(), str);
        pthread_join(th1, NULL);
        pthread_join(th2, NULL);
        return 0;
    }

       运行结果是:

    Thread b757b6c0:allocated key 0
    Thread b757b6c0:allocating buffer at 0x9a99008
    Thread b757b6c0:"Main process Result ofinitial thread"
    Thread b6d79b40:allocating buffer at 0xb6400468
    Thread b6d79b40:"Result of second thread"
    Thread b6d79b40:freeing buffer at 0xb6400468
    Thread b757ab40:allocating buffer at 0xb6400468
    Thread b757ab40:"Result of first thread"
    Thread b757ab40:freeing buffer at 0xb6400468
  • 相关阅读:
    如何在WinPE下安装xp安装版
    好用、功能强大的JQuery弹出层插件
    设计模式-旧话重提之类工厂的使用
    How can I manage Internet Explorer Security Zones via the registry?
    设计模式行为模式Behavioral Patterns()之FlexibleService模式
    how to design a new tree view control
    在C#中通过webdav操作exchange
    Yahoo! User Interface Library (哈偶然发现了这个东西)
    设计模式[2]旧话重提之工厂模式
    const和static readonly 的区别
  • 原文地址:https://www.cnblogs.com/wangle1001986/p/3251381.html
Copyright © 2011-2022 走看看