gpt4 book ai didi

c - 使函数线程安全 : Thread-specific data vs mutex

转载 作者:行者123 更新时间:2023-12-03 12:48:07 28 4
gpt4 key购买 nike

Linux 编程接口(interface),在§31.3.4 使用线程特定数据 API 中,它给出了使用线程特定数据制作线程不安全函数 thead 安全:

Thead 不安全版本:

/* Listing 31-1 */

/* strerror.c

An implementation of strerror() that is not thread-safe.
*/
#define _GNU_SOURCE /* Get '_sys_nerr' and '_sys_errlist'
declarations from <stdio.h> */
#include <stdio.h>
#include <string.h> /* Get declaration of strerror() */

#define MAX_ERROR_LEN 256 /* Maximum length of string
returned by strerror() */

static char buf[MAX_ERROR_LEN]; /* Statically allocated return buffer */

char *
strerror(int err)
{
if (err < 0 || err >= _sys_nerr || _sys_errlist[err] == NULL) {
snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);
} else {
strncpy(buf, _sys_errlist[err], MAX_ERROR_LEN - 1);
buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */
}

return buf;
}

具有线程特定数据的线程安全版本:

/* Listing 31-3 */

/* strerror_tsd.c

An implementation of strerror() that is made thread-safe through
the use of thread-specific data.

See also strerror_tls.c.
*/
#define _GNU_SOURCE /* Get '_sys_nerr' and '_sys_errlist'
declarations from <stdio.h> */
#include <stdio.h>
#include <string.h> /* Get declaration of strerror() */
#include <pthread.h>
#include "tlpi_hdr.h"

static pthread_once_t once = PTHREAD_ONCE_INIT;
static pthread_key_t strerrorKey;

#define MAX_ERROR_LEN 256 /* Maximum length of string in per-thread
buffer returned by strerror() */

static void /* Free thread-specific data buffer */
destructor(void *buf)
{
free(buf);
}

static void /* One-time key creation function */
createKey(void)
{
int s;

/* Allocate a unique thread-specific data key and save the address
of the destructor for thread-specific data buffers */

s = pthread_key_create(&strerrorKey, destructor);
if (s != 0)
errExitEN(s, "pthread_key_create");
}

char *
strerror(int err)
{
int s;
char *buf;

/* Make first caller allocate key for thread-specific data */

s = pthread_once(&once, createKey);
if (s != 0)
errExitEN(s, "pthread_once");

buf = pthread_getspecific(strerrorKey);
if (buf == NULL) { /* If first call from this thread, allocate
buffer for thread, and save its location */
buf = malloc(MAX_ERROR_LEN);
if (buf == NULL)
errExit("malloc");

s = pthread_setspecific(strerrorKey, buf);
if (s != 0)
errExitEN(s, "pthread_setspecific");
}

if (err < 0 || err >= _sys_nerr || _sys_errlist[err] == NULL) {
snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);
} else {
strncpy(buf, _sys_errlist[err], MAX_ERROR_LEN - 1);
buf[MAX_ERROR_LEN - 1] = '\0'; /* Ensure null termination */
}

return buf;
}

在本章的总结部分,它说:

...
Most of the functions specified in SUSv3 are required to be thread-safe. SUSv3 also lists a small set of functions that are not required to be thread-safe. Typically, these are functions that employ static storage to return information to the caller or to maintain information between successive calls. By definition, such functions are not reentrant, and mutexes can’t be used to make them thread-safe. We considered two roughly equivalent coding techniques—thread-specific data and thread-local storage—that can be used to render an unsafe function thread-safe without needing to change its interface.
...

我了解使用特定于线程的数据旨在将线程不安全的函数变为线程安全的函数,无需更改函数的接口(interface)/签名

但是我不明白:

By definition, such functions are not reentrant, and mutexes can’t be used to make them thread-safe.

问题:

  1. 为什么说“不能使用互斥锁……而特定于线程的数据可以……”?是否有任何条件可以使线程不安全的函数仅使用特定于线程的数据而不使用互斥锁实现线程安全?

  2. 我认为我可以将线程不安全的 strerror() 变为线程安全的,只需添加一个互斥量即可。与使用 thread-specifia 数据发布的相比,它有什么区别吗? (可能会损失一些并发效率?因为我要使用互斥锁来锁定访问静态变量的代码)

最佳答案

I think I can make the thread-unsafe strerror() to a thead-safe one, simply adding a mutex.

嗯,你错了,SUSv3 的作者是对的。

要了解为什么互斥量不能使这些不可重入函数成为线程安全的,请考虑strerror 的原始(不安全)代码。

添加互斥量可以使 strerror 本身安全。

也就是说,我们可以避免在不同线程中对 strerror 的并发调用之间发生数据竞争。

这就是我认为您的想法:在开始时锁定互斥量,在结束时解锁,工作完成。很简单。

然而,它也是完全没有值(value)的 - 因为调用者永远无法安全地使用返回的缓冲区:它仍然与其他线程共享并且互斥锁仅在 inside strerror 的调用中保护它

使函数安全和有用(使用互斥锁)的唯一方法是让调用者持有互斥锁直到它完成使用缓冲区,这.. . 需要更改界面。

关于c - 使函数线程安全 : Thread-specific data vs mutex,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59491236/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com