0

我想确定是否可以同时从多个线程调用 C 中的某些函数,以便了解是否需要使用互斥锁来保护它。实现和定义函数的文件没有任何互斥机制,因此有可能只有一个线程访问该函数,但有可能多个线程访问。

我想添加一个线程本地存储变量,我在启动函数时递增,在退出函数时递减。如果递减后变量的值大于 0,则多线程访问该函数。

这是我的代码:

#include <stdio.h>

static __thread int threadCounter = 0;

void f(void)
{
    threadCounter++;

    // do something

    threadCounter--;
    printf("threadCounter: %d\n", threadCounter);
}

a想知道这个解决方案是否足以确定多个线程是否访问一个函数以及是否有更好的方法来实现这一点。

4

3 回答 3

2

根据定义,线程局部变量仅对当前线程可见,您的解决方案将不起作用。但是你的方法很好。您应该使用受互斥锁保护的变量,而不是使用线程局部变量。

于 2019-05-21T10:55:01.260 回答
2

来自GCC 文档:“线程局部存储 (TLS) 是一种分配变量的机制,使得每个现有线程都有一个变量实例。”
因此,您的解决方案将始终表明当时只有一个线程访问您的函数,即使情况并非如此。您应该使用在线程之间共享的变量。但是使用 volatile 仍然不是一个好的解决方案,因为如果同时有多个线程访问它,则该值可能不是一个好的值。

总之,我认为这样做的更好方法是设置互斥锁并使用 pthread_mutex_trylock 函数来检测是否有多个线程试图调用您的函数。

于 2019-05-21T10:58:55.203 回答
1

该测试要么使用局部变量,要么本身不是线程安全的。无论哪种情况,它都不能作为证据。如果要使用计数器,则必须使用互斥锁或临界区之类的东西来保护它。几乎没有办法解决这个问题。

但是还有另一种方法可以更好地做到这一点,为您提供有关谁调用该函数的确切信息,同时不必修改实际函数。您可以创建一个“模拟”功能:

#define f() ( print(__func__), f() )

这将打印线程回调函数的名称,然后调用实际函数f()。这是有效的,因为预处理器令牌f()在任何函数调用之前被评估。

我将该函数编写为自定义函数print,因为如果您使用printfetc,您仍然会遇到多个线程尝试同时访问 stdout 的问题。因此,自定义print函数必须包含线程安全的手段。

于 2019-05-21T10:56:08.900 回答