【问题标题】:How to determine that multiple threads call function simultaneously in C?如何确定C中多个线程同时调用函数?
【发布时间】:2019-05-21 20:45:08
【问题描述】:

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

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

这是我的代码:

#include <stdio.h>

static __thread int threadCounter = 0;

void f(void)
{
    threadCounter++;

    // do something

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

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

【问题讨论】:

  • 貌似线程局部变量不能成功检测到你想要的东西。根据定义,它与单个线程隔离。
  • 您似乎需要与 TLS 变量相反 - 多个线程应该可以访问的一些易失性变量。 TLS 变量仅对其所在存储的线程可见,即每个线程将“看到”其自己的此类变量版本。
  • @EricPostpischil 我想知道线程是否可以同时访问该函数。
  • 线程访问“代码区域”从来没有问题,因为代码是只读的。只有当代码使用非自动存储变量时才会有问题。如果一个函数调用其他函数,那么实现互斥锁应该在将使用共享数据(变量或资源)的最低级别。我认为这是一个适当的设计问题。
  • 如果多个线程调用该函数(根本没有),并且没有互斥锁,并且 f 操作的东西不是多线程安全的,那么你应该放入互斥锁,除非你可以证明调用不会同时发生的代码的其他方面(例如,f 仅在线程完成了排除多个线程的其他操作后才被调用)。有一些技术可以揭示 f 在实验运行中是否被同时调用,但f 可能在实验运行中从未被同时调用,但在实践中最终会被同时调用。

标签: c multithreading


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      我将函数编写为自定义函数print,因为如果您使用printf 等,您仍然会遇到多个线程尝试同时访问标准输出的问题。所以自定义print 函数必须包含线程安全的手段。

      【讨论】:

        猜你喜欢
        • 2013-03-03
        • 1970-01-01
        • 2019-07-23
        • 1970-01-01
        • 1970-01-01
        • 2014-11-10
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        相关资源
        最近更新 更多