全局/本地/静态互斥量之间的区别?

Difference between global / local / static Mutex?

互斥量用于防止两个或多个线程同时访问同一资源(文件、变量、..)。这可以防止竞争条件的发生。

每个线程都有自己的堆栈。这意味着当一个线程调用一个函数时,该线程将拥有该函数中定义的局部变量的唯一副本。但是如果一个局部变量被定义为static,那么只会创建这个变量的一个副本,这个副本将被所有线程访问。

非静态局部互斥量仍然有用:如果您有一个创建其他线程并等待它们完成的主线程,互斥量可以是主线程中的局部变量,它会通过指向其他线程的互斥锁的指针。这只有在保证主线程比其他线程长的情况下才有效。

如果 mutex 变量在线程函数中声明为 static,它将在使用该函数的不同线程之间共享,并且它们可以使用它进行同步。这是因为 static 变量与全局变量具有相同的生命周期(并且只有一个唯一副本)。但是,这仅在您的线程库不需要函数调用来初始化互斥锁时才有效,因为没有合适的地方进行初始化。

另一种选择是动态分配互斥锁,或者更常见的是,将其作为动态分配结构的成员。然后,您可以将指向互斥锁(或包含结构)的指针传递给所有需要它的线程。

关于你的最后一个问题:将全局变量定义为static意味着它只在当前翻译单元中可见。它不会影响它的生命周期,因此对于这个用例,它的工作方式类似于非静态全局变量(只要您只需要在一个 .c 文件中访问它)。

static in C 表示它仅在该文件中可见。因此,如果所有使用 static mutex 的函数都位于同一文件中,那么它们将共享相同的互斥锁。如果 mutex 是从多个文件中的函数访问的,那么它必须是 global。通常,您有一个全局状态变量并与其关联的全局互斥体。

// in types.h
typedef struct {
  pthread_mutex_t lock;
  int val;
} state_t;


// in shared.h
extern state_t global_state;

// in code
#include "types.h"
#include "shared.h"

int foo() {
   pthread_mutex_lock(global_state.lock);
   global_state.val = STATE_FOO;
   pthread_mutex_unlock(global_state.lock);
}

每个函数的互斥体没有意义。

局部于线程回调函数是无用的 - 多个函数之间不共享的互斥锁没有多大意义。但是,为了减少 scope/global 命名空间混乱,您可以将其设为本地 static,然后通过指针在函数之间共享它。例如让主线程创建它,然后在创建过程中将它传递给不同的线程。这通常是最有意义的 - 让一个线程负责创建和清理项目中的所有线程和互斥锁等。

一个典型的错误是让一个线程通过将具有自动存储(保存在堆栈中)的局部变量传递给线程来创建资源,然后该线程超出范围并且变量变为无效。因此,通常对此类变量使用 static 或动态内存分配,以便它们在整个程序执行过程中持续存在。

“全球”一词令人困惑且定义不明确。通常它对整个项目意味着全局。在任何函数外部声明的变量都具有 文件范围 ,但这样的变量可能具有外部或内部链接。外部意思是“全球”。但是,如果您声明一个文件范围变量 static,它会获得内部链接并且仅对声明它的 .c 文件可见。这是一件好事,因为它缩小了范围并防止使用全局变量进行意大利面条式编程。