zoukankan      html  css  js  c++  java
  • 线程专有数据(ThreadSpecific Data)

    Unlike processes, all threads in a single program share the same address space.This
    means that if one thread modifies a location in memory (for instance, a global vari-able),

    the change is visible to all other threads.This allows multiple threads to operate
    on the same data without the use interprocess communication mechanisms

    Each thread has its own call stack, however.This allows each thread to execute different

    code and to call and return from subroutines in the usual way.

    As in a single-threaded program, each invocation of a subroutine in each thread has its own set of
    local variables, which are stored on the stack for that thread.
    Sometimes, however, it is desirable to duplicate a certain variable so that each
    thread has a separate copy. GNU/Linux supports this by providing each thread with a
    thread-specific data area.The variables stored in this area are duplicated for each thread,
    and each thread may modify its copy of a variable without affecting other threads.
    Because all threads share the same memory space, thread-specific data may not be
    accessed using normal variable references. GNU/Linux provides special functions for
    setting and retrieving values from the thread-specific data area。

    You may create as many thread-specific data items as you want, each of type void*.
    Each item is referenced by a key.To create a new key, and thus a new data item for
    each thread, use pthread_key_create.The first argument is a pointer to a
    pthread_key_tvariable.That key value can be used by each thread to access its own
    copy of the corresponding data item.The second argument to pthread_key_tis a
    cleanup function. If you pass a function pointer here, GNU/Linux automatically calls
    that function when each thread exits, passing the thread-specific value corresponding
    to that key.This is particularly handy because the cleanup function is called even if the
    thread is canceled at some arbitrary point in its execution. If the thread-specific value
    is null, the thread cleanup function is not called. If you don’t need a cleanup function,
    you may pass null instead of a function pointer.
    After you’ve created a key, each thread can set its thread-specific value corresponding

    to that key by calling pthread_setspecific.The first argument is the key, and the
    second is the void* thread-specific value to store.To retrieve a thread-specific data
    item, call pthread_getspecific, passing the key as its argument.
    Suppose, for instance, that your application divides a task among multiple threads.
    For audit purposes, each thread is to have a separate log file, in which progress messages

    for that thread’s tasks are recorded.The thread-specific data area is a convenient
    place to store the file pointer for the log file for each individual thread.

    你想创建多少线程专有数据对象都可以;它们的类型都是void*。每个数据对象都通过
    一个键值进行映射。要创建一个新键值从而为每个线程新创建一个数据对象,调用
    pthread_key_create函数。第一个参数是一个指向pthread_key_t类型变量的指针。新创建
    的键值将被保存在这个变量中。随后,这个键值可以被任意线程用于访问对应数据对象
    的属于自己的副本。传递给pthread_key_create的第二个参数是一个清理函数,如果你在这
    里传递一个函数指针,则GNU/Linux系统将在线程退出的时候以这个键值对应的数据对象
    为参数自动调用这个清理函数。清理函数非常有用,因为即使当线程在任何一个非特定运行
    时刻被取消,这个线程函数也会被保证调用。如果对应的数据对象是一个空指针,清理函数
    将不会被调用。如果你不需要调用清理函数,你可以在这里传递空指针。
    创建了键值之后,可以通过调用pthread_setspecific设定相应的线程专有数据值。第一
    个参数是键值,而第二个参数是一个指向要设置的数据的void*指针。以键值为参数调用
    pthread_getspecific可重新获取一个已经设置的线程专有数据。
    假设这样一种情况,你的程序将一个任务分解以供多个线程执行。为了进行审计,每个
    线程都将分配一个单独的日志文件,用于记录对应线程的任务完成进度。线程专有数据区是
    为每个单独线程保存对应的日志文件指针的最方便的地点。


    Listing 4.7 shows how you might implement this.The mainfunction in this sample
    program creates a key to store the thread-specific file pointer and then stores it in
    thread_log_key. Because this is a global variable, it is shared by all threads.When each
    thread starts executing its thread function, it opens a log file and stores the file pointer
    under that key. Later, any of these threads may call write_to_thread_logto write a
    message to the thread-specific log file.That function retrieves the file pointer for the
    thread’s log file from thread-specific data and writes the message.

    Listing 4.7 (tsd.c) Per-Thread Log Files Implemented with Thread-Specific Data
    #include <malloc.h>
    #include <pthread.h>
    #include <stdio.h>
    /* The key used to associate a log file pointer with each thread. */
    static pthread_key_t thread_log_key;
    /* Write MESSAGE to the log file for the current thread. */
    void write_to_thread_log (const char* message)
    {
    FILE* thread_log = (FILE*) pthread_getspecific (thread_log_key);
    fprintf (thread_log, “%s\n”, message);
    }
    /* Close the log file pointer THREAD_LOG. */
    void close_thread_log (void* thread_log)

    {
    fclose ((FILE*) thread_log);
    }
    void* thread_function (void* args)
    {
    char thread_log_filename[20];
    FILE* thread_log;
    /* Generate the filename for this thread’s log file. */
    sprintf (thread_log_filename, “thread%d.log”, (int) pthread_self ());
    /* Open the log file. */
    thread_log = fopen (thread_log_filename, “w”);
    /* Store the file pointer in thread-specific data under thread_log_key. */
    pthread_setspecific (thread_log_key, thread_log);
    write_to_thread_log (“Thread starting.”);
    /* Do work here... */
    return NULL;
    }
    int main ()
    {
    int i;
    pthread_t threads[5];
    /* Create a key to associate thread log file pointers in
    thread-specific data. Use close_thread_log to clean up the file
    pointers. */
    pthread_key_create (&thread_log_key, close_thread_log);
    /* Create threads to do the work. */
    for (i = 0; i < 5; ++i)
    pthread_create (&(threads[i]), NULL, thread_function, NULL);
    /* Wait for all threads to finish. */
    for (i = 0; i < 5; ++i)
    pthread_join (threads[i], NULL);
    return 0;
    }
    Observe that thread_functiondoes not need to close the log file.That’s because when
    the log file key was created,close_thread_logwas specified as the cleanup function
    for that key.Whenever a thread exits, GNU/Linux calls that function, passing the
    thread-specific value for the thread log key.This function takes care of closing the
    log file.

  • 相关阅读:
    洛谷 P1692 部落卫队
    洛谷 P1113 杂务
    洛谷 P1546 最短网络 Agri-Net
    洛谷 P2121 拆地毯
    洛谷 P2728 纺车的轮子 Spinning Wheels
    洛谷 P2126 Mzc家中的男家丁
    线段树双标记——乘法和加法
    A. Feed the cat
    洛谷 P1535 游荡的奶牛
    BZOJ1050 [HAOI2006]旅行
  • 原文地址:https://www.cnblogs.com/michile/p/2891085.html
Copyright © 2011-2022 走看看