Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 与线程共享变量的最佳方法_C_Multithreading_Global Variables - Fatal编程技术网

C 与线程共享变量的最佳方法

C 与线程共享变量的最佳方法,c,multithreading,global-variables,C,Multithreading,Global Variables,我在一个mingw程序中工作,除了主执行之外,还有两个线程(pthread\u t)。每个线程包含一个无限循环,用于与外部仪器进行连续通信,每个通信具有不同的速度和协议。主程序只是在运行时根据用户请求显示仪器数据。线程中的无限循环只有在main中将“keepalive”变量设置为0时才会退出。 为了在线程之间交换数据,我想知道我知道的两种方法的优缺点: 向线程传递参数(可以使用pthread_create:*arg的最后一个参数传递结构) 使用全局变量并控制并发性(pthread\u mut

我在一个mingw程序中工作,除了主执行之外,还有两个线程(pthread\u t)。每个线程包含一个无限循环,用于与外部仪器进行连续通信,每个通信具有不同的速度和协议。主程序只是在运行时根据用户请求显示仪器数据。线程中的无限循环只有在main中将“keepalive”变量设置为0时才会退出。 为了在线程之间交换数据,我想知道我知道的两种方法的优缺点:

  • 向线程传递参数(可以使用pthread_create:*arg的最后一个参数传递结构)

  • 使用全局变量并控制并发性(pthread\u mutex\u lockpthread\u mutex\u unlock

实际上,我正在使用这两种方法(主要是因为我需要一个早期的“工作程序版本”)。作为我提到的变量交换的一个例子:

  • 我将“keepalive”变量定义为全局变量(在线程进入无止境循环时共享它)
  • 我通过struct传递通信配置数据
  • 我通过一个全局数组(在无限循环中更新)将仪器数据检索到main
  • 我正在检索文件句柄并与结构通信(最后,正确地关闭和释放所有内容)
  • 对于使用全局变量与使用带原子变量的struct相比的缺点,我希望能提出一些建议。(代码清洁度、速度、效率、cpu/内存使用…)


    谢谢。

    如果可以的话,尽量避免使用全局变量,因为它们可能会导致并发问题,并使代码的可读性大大降低。我建议创建一个包含原子类型变量的userdata结构。大概是这样的:

    struct user_data {
      atomic_bool myBool;
      atomic_int myInt;
    };
    
    int main() {
      pthread_t myThread;
    
      struct user_data userdata = {
        .myBool = &ATOMIC_VAR_INIT(false),
        .myInt = &ATOMIC_VAR_INIT(0)
      };
      if (pthread_create(&myThread, NULL, myFunction, &userdata) {
        // error handling
      }
    }
    
    这将避免并发问题,并使代码更具可读性。 要修改原子变量,请使用原子操作,例如:

    原子存储
    原子负载
    原子提取添加


    这是原子操作库的一个例子。

    几乎所有人都认为不应该使用全局变量。(我想你可能还不明白。)

    然后

    […]因为我关心速度和效率

    您正在利用锁定来同步访问。因此,忘了它吧,由此产生的开销会影响其他任何东西。由于(链接时间)已知地址,使用全局地址可能会“更快”。不过,我严重怀疑这是否有任何关联不要在未咨询探查器的情况下过早优化。

    全局变量的一个缺点是测试线程之间的通信变得更加困难。当传递
    结构时,您可以轻松启动另一个线程,并让该线程与要测试其通信的端点通信。您不需要为此更改任何端点,只需更改这些线程的启动方式即可

    此外,由于类似的原因,扩展应用程序并不容易。假设您有两个线程,例如“searcher”(用于搜索某些数据)和“indexer”(负责存储匹配项,并可能分离进一步的操作)。如果他们通过一个全局变量进行通信,您将如何添加另一个searcher线程?您必须使用另一个全局变量在新的搜索器和索引器之间进行通信,复制大部分搜索器线程(所有更改都是用于通信的变量)。与传递包含“通信通道”的结构相比:在这里,您甚至不需要触摸搜索程序代码,只需启动另一个。(不过,在这两个示例中,索引器必须更改为能够有多个输入源)


    最后,通过线程开始时的结构传递“通信通道”可以隐藏通信通道,从而限制哪些线程可以访问它。当试图找出谁从该频道写/读时,这可能非常有价值。(“是哪个线程编写了sh#t?”)

    避免使用全局变量,这是一个通用的技巧,如果您使用线程与否,它同样有效。您肯定应该使用原子变量。我看到由于“基于意见”的投票结果非常接近。考虑到问题目前的措辞,这可能是真的。将其更改为询问使用全局变量进行线程同步可能存在的缺点,可以缓解这一问题。再次,在回答了这个问题之后,我想到这个问题可能更适合程序员。stackexchange.com,或者?
    struct user_data {
      atomic_bool myBool;
      atomic_int myInt;
    };
    
    int main() {
      pthread_t myThread;
    
      struct user_data userdata = {
        .myBool = &ATOMIC_VAR_INIT(false),
        .myInt = &ATOMIC_VAR_INIT(0)
      };
      if (pthread_create(&myThread, NULL, myFunction, &userdata) {
        // error handling
      }
    }