线程专有数据(Thread-Specific 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.

转载于:https://www.cnblogs.com/michile/archive/2013/02/03/2891085.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值