使用具有共享全局变量的线程
Posted
技术标签:
【中文标题】使用具有共享全局变量的线程【英文标题】:using threads with a shared global variable 【发布时间】:2015-12-03 23:41:04 【问题描述】:当线程访问共享全局变量时,我无法想出一种算法来确保互斥。我正在尝试编写一个可以使用全局变量的线程函数,而不是将其切换为局部变量。
到目前为止我有这个代码:
int sumGlobal = 0;
void sumArray(int** array, int size)
for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
sumGlobal += array[i][j];
int main()
int size = 4000;
int numThreads = 4;
int** a2DArray = new int*[size];
for (int i=0; i<size; i++)
a2DArray[i] = new int[size];
for (int j=0; j<dim; j++)
a2DArray[i][j] = genRandNum(0,100);
std::vector<std::future<void>> thread_Pool;
for (int i = 0; i < numThreads; ++i)
thread_Pool.push_back( std::async(launch::async,
sumArray, a2DArray, size));
我不确定如何保证sumGlobal
不会被每个线程重写。我想正确更新它,以便每个线程在完成时将其值添加到全局变量中。我只是想学习线程,而不是局限于非空函数。
【问题讨论】:
您有两个选择:1)使用锁进行互斥。 2)使用原子类型和操作来避免对锁的需要。 【参考方案1】:制作变量atomic:
#include <atomic>
...
std::atomic<int> sumGlobal 0;
原子变量不受数据竞争的影响:即使有多个线程尝试读取和写入它,它也表现良好。原子性是通过互斥还是无锁方式实现的,由实现来决定。当您使用 +=
以原子方式更新变量时,您的示例中不存在不一致的风险。
nice video 更详细地向您解释什么是原子,为什么需要它们,以及它们是如何工作的。
您也可以保持变量原样并使用互斥锁/lock_gard 来保护它,正如我的@Miles Budnek 所解释的那样。问题是,一次只有一个线程可以执行受互斥锁保护的代码。在您的示例中,这意味着不同线程中的处理不会真正同时进行。原子方法应该具有卓越的性能:一个线程可能仍然计算索引并读取数组,而另一个线程正在更新全局变量。
【讨论】:
谢谢,虽然不是我想要的解决方案。您是否知道在保持变量不变的同时实现这一点的方法?虽然在旁注中,但在尝试了您的建议后,我得到了编译错误。不知道为什么。 @foolsgold 这是一个很小的更改,可能是解决您问题的最佳解决方案。为什么它不是您所追求的“解决方案”? @foolsgold 我已经更新了初始化以消除所有编译器上的错误消息。我已经完成了互斥锁以允许更长时间地冻结变量的值,但我不会在您的示例中推荐这种方法。 感谢视频,非常有趣!【参考方案2】:如果您不想像@Christophe 建议的那样使用std::atomic<int>
之类的同步对象,您可以使用std::mutex
和std::lock_guard
手动同步对总和的访问。
int sumGlobal = 0;
std::mutex sumMutex;
void sumArray(...)
for(...)
for(...)
std::lock_guard<std::mutex> lock(sumMutex);
sumGlobal += ...;
请记住,所有锁定和解锁都会产生相当多的开销。
【讨论】:
感谢您的回复,这些方法很有帮助。只是让你知道,这不会编译,error: missing template arguments before 'lock.'
我通过添加<std::mutex>
来编译它,但结果不正确。与非线程版本相比,这会产生不正确的 sumGlobal
值。如果需要,我可以包含非线程版本。
糟糕,修复了缺少的模板参数。请注意,我只是复制了该函数,因为这不是您要问的,但它不会产生数组的总和。 sumGlobal
最终将成为您当前代码的numThreads * sum(a2DArray)
,因为每个线程都在对整个数组求和。如果您想使用线程对数组求和,则需要以某种方式分解数组以告诉每个线程要求和的部分。以上是关于使用具有共享全局变量的线程的主要内容,如果未能解决你的问题,请参考以下文章