POSIX 线程键值

更新时间:
2024-03-14
下载文档

POSIX 线程键值

POSIX 线程键值又称作线程私有数据。

从本质上讲,线程键值对于多个线程具有相同的名字不同的值,如下图所示。在“CPU亲和”我们讨论了线程私有数据在多线程安全方面的作用,下面介绍 POSIX 线程键值的 API 及其使用方法。

注意:
SylixOS 中由全局的链表管理所有的键,因此 SylixOS 中的键是整个系统可见的。

#include <pthread.h>
int  pthread_key_create(pthread_key_t *pkey, void (*destructor)(void *));
int  pthread_key_delete(pthread_key_t  key);

函数 pthread_key_create 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 输出参数 pkey 返回创建的线程键值。
  • 参数 destructor 是删除函数。

函数 pthread_key_delete 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 key 是要删除的键。

调用 pthread_key_create 函数可以创建一个键,因为同一个进程中的所有线程都可以使用这个键,所以这个键通常定义为一个全局变量,如果参数 destructor 不为 NULL,则在 key 删除的时候自动被调用,如果无需释放任何内存,那么可将参数 destructor 置为 NULL。调用 pthread_key_delete 函数将删除一个键。需要注意的是,参数 destructor 函数中不能删除 key,因为 key 属于整个系统,也就是说所有线程是可见的,如果在 destructor 函数中删除了 key 其他线程可能再次访问,这将造成不可预知的错误。

一个 key 对应唯一一个 destructor 函数,该函数被所有线程共享。destructor 函数必须在 key 创建时指定且不能更改。如果指定了 destructor 函数,当线程退出时 SylixOS 会自动调用该清除函数。

pthread_key_create 函数返回的 key 是 pthread_key_t 类型,这一类型在不同系统实现中可能代表不同的类型,有些系统中 key 值只是数组的索引,然而在 SylixOS 中 key 值则代表一个地址值,因此,我们试图去打印一个 key 值,可能不会得到预想的结果。

调用 pthread_setspecific 函数可以将线程私有数据与 key 进行关联(key 由之前的 pthread_key_create 调用返回),pthread_getspecific 函数与 pthread_setspecific 函数的功能相反,返回本线程中与 key 相关联的私有数据(pvalue)。

#include <pthread.h>
int    pthread_setspecific(pthread_key_t  key, const void  *pvalue);
void  *pthread_getspecific(pthread_key_t  key);

函数 pthread_setspecific 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 key 是键。
  • 参数 pvalue 是要设置的值。

函数 pthread_getspecific 原型分析:

  • 此函数成功返回 0,失败返回错误号。
  • 参数 key 是键。

pthread_setspecific 函数参数 pvalue 是一个无类型指针,这可以指向任何数据类型,包括复杂的数据结构。当线程终止时,会将该指针作为参数传递给与 key 对应的 destructor 函数(pthread_key_create 参数)。

下面程序展示了 POSIX 线程键的使用。

#include <pthread.h>
#include <stdio.h>

static  char          *str = "this is pthread key.";
static  pthread_key_t  key;

void *thread (void *arg)
{
    void  *keyval;

    pthread_setspecific(key, str);
    sleep(2);
    keyval = pthread_getspecific(key);
    fprintf(stdout, "keyval child thread is: %s\n", (char *)keyval);

    return  (NULL);
}

int main (int argc, char *argv[])
{
    pthread_t  tid;
    int        ret;
    void      *keyval;

    ret = pthread_key_create(&key, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread key create failed.\n");
        return  (-1);
    }
    ret = pthread_create(&tid, NULL, thread, NULL);
    if (ret != 0) {
        fprintf(stderr, "pthread create failed.\n");
        return  (-1);
    }
    keyval = pthread_getspecific(key);
    fprintf(stdout, "keyval main thread is: %s\n", (char *)keyval);
    pthread_join(tid, NULL);
    pthread_key_delete(key);
    return  (0);
}

在 SylixOS Shell 下运行程序,从程序运行结果可见,程序中的两个线程共用一个键 key,但在子线程中设置的键值在主线程是不可见的。正如下图所示的那样,虽然线程 ID_x 和线程 ID_y 共用键 key_n,但是它们的值 value_x 和 value_y 是不同的。

# ./POSIX_Thread_Key
keyval main thread is: (null).
keyval child thread is: this is pthread key.
文档内容是否对您有所帮助?
有帮助
没帮助