博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程专有数据(Thread-Specific Data)
阅读量:5922 次
发布时间:2019-06-19

本文共 5903 字,大约阅读时间需要 19 分钟。

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

你可能感兴趣的文章
POJ 3278 Catch That Cow (附有Runtime Error和Wrong Answer的常见原因)
查看>>
numpy 三个点的使用[...]
查看>>
Codeforces Round #327 (Div. 2) B Rebranding(映射)
查看>>
NHibernate初学者指南(3):创建Model
查看>>
C++——this指针
查看>>
关于MVVM和RAC的一些拓展阅读
查看>>
day7
查看>>
python3 爬取百合网的女人们和男人们
查看>>
模式对象管理
查看>>
Java学习方法浅谈
查看>>
Linux 命令 "cp" 代码实现简介
查看>>
开启我的编程之路
查看>>
POJ-3186_Treats for the Cows
查看>>
bzoj1010: [HNOI2008]玩具装箱toy
查看>>
四叶草——计划会议
查看>>
UVa 1339,紫书P73,词频
查看>>
JavaScript-事件
查看>>
MarkDown换行
查看>>
【温故而知新】HTTP 报文
查看>>
部分关键字段重复的记录(保留最后记录)
查看>>