【问题标题】:Difference between global / local / static Mutex?全局/本地/静态互斥体之间的区别?
【发布时间】:2020-07-10 07:41:41
【问题描述】:

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

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

  • 这是否意味着 本地 NON-static 互斥锁没用?

  • static 本地互斥锁有用吗?也许是为了守护static 局部变量?

  • 将全局互斥锁定义为static 有何不同?

【问题讨论】:

    标签: c multithreading mutex


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:
        C 中的

        static 表示它仅在该文件中可见。因此,如果所有使用静态互斥锁的函数都位于同一个文件中,那么它们将共享同一个互斥锁。如果互斥锁是从多个文件中的函数访问的,那么它必须是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);
        }
        

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

        【讨论】:

        • 我建议不要以这种方式使用全局变量,没有明显的需要。最好将互斥锁放在一个文件本地,然后在创建期间将其传递给不同的线程。
        • 好吧,你应该避免使用全局变量。在“生产”代码中,您将创建一个 state_t 实例并传递它。
        猜你喜欢
        • 1970-01-01
        • 2010-10-31
        • 2016-06-01
        • 2018-12-22
        • 1970-01-01
        • 2014-09-26
        • 1970-01-01
        • 2014-06-30
        • 1970-01-01
        相关资源
        最近更新 更多