我想确定是否可以从多个线程中同时调用C中的某些函数,以便了解是否需要使用互斥锁来保护它。实现和定义函数的文件没有任何互斥机制,因此有可能只有一个线程访问过该函数,但有可能多个线程访问了该函数。
我想添加一个线程本地存储变量,该变量在启动函数时增加,在退出函数时减少。如果递减后变量的值大于0,则有多个线程访问该函数。
这是我的代码:
#include <stdio.h>
static __thread int threadCounter = 0;
void f(void)
{
threadCounter++;
// do something
threadCounter--;
printf("threadCounter: %d\n", threadCounter);
}
一个人想知道这种解决方案是否足以确定多个线程是否访问一个函数以及是否有更好的方法来完成此任务。
答案 0 :(得分:2)
根据定义,线程局部变量仅对当前线程可见,您的解决方案将无法使用。但是您的方法很好。而不是使用线程局部变量,您应该使用受互斥锁保护的变量。
答案 1 :(得分:2)
来自GCC documentation:
“线程本地存储(TLS)是一种分配变量的机制,这样每个现有线程都有一个变量实例。”
因此,您的解决方案将始终指示当时只有一个线程访问您的函数,即使不是这种情况。您应该使用线程之间共享的变量。但是,使用volatile仍然不是一个好的解决方案,因为如果同时有多个线程对其进行访问,则该值可能不是一个好的解决方案。
总而言之,我认为这样做的更好方法是设置一个互斥锁,并使用pthread_mutex_trylock函数检测是否有多个线程试图调用您的函数。
答案 2 :(得分:1)
此测试正在使用局部变量,或者它本身不是线程安全的。无论哪种情况,它都不能用作证明。如果要使用计数器,则必须使用互斥或关键部分来保护它。几乎没有办法解决这个问题。
但是,还有另一种方法可以更好地做到这一点,为您提供有关谁调用了该函数的确切信息,而同时又不必修改实际函数。您可以创建一个“模拟”功能:
#define f() ( print(__func__), f() )
这将打印线程回调函数的名称,然后调用实际函数f()
。之所以可行,是因为在任何函数调用之前都要评估预处理器令牌f()
。
我将函数编写为自定义的print
,因为如果使用printf
等,您仍然遇到多线程尝试一次访问stdout的问题。因此,自定义{{1 }}函数必须包含线程安全手段。