C++ 同时从不同线程填充数组c++;

C++ 同时从不同线程填充数组c++;,c++,arrays,multithreading,C++,Arrays,Multithreading,首先,我认为有一点很重要,那就是我是多线程新手,对多线程知之甚少。我尝试用C++编写一些C++程序,并遇到了一个问题(问题),现在我将向你解释: 我想用几个线程来填充一个数组,下面是我的代码: static const int num_threads = 5; int A[50], n; //------------------------------------------------------------ void ThreadFunc(int tid) { for (int q

首先,我认为有一点很重要,那就是我是多线程新手,对多线程知之甚少。我尝试用C++编写一些C++程序,并遇到了一个问题(问题),现在我将向你解释:

我想用几个线程来填充一个数组,下面是我的代码:

static const int num_threads = 5;
int A[50], n;

//------------------------------------------------------------
void ThreadFunc(int tid)
{
    for (int q = 0; q < 5; q++)
    {
        A[n] = tid;
        n++;
    }
}

//------------------------------------------------------------
int main()
{
        thread t[num_threads];
        n = 0;
        for (int i = 0; i < num_threads; i++)
        {
            t[i] = thread(ThreadFunc, i);
        }

        for (int i = 0; i < num_threads; i++)
        {
            t[i].join();
        }
        for (int i = 0; i < n; i++)
            cout << A[i] << endl;

    return 0;
}
static const int num_threads=5;
int A[50],n;
//------------------------------------------------------------
void ThreadFunc(整数tid)
{
对于(int q=0;q<5;q++)
{
A[n]=tid;
n++;
}
}
//------------------------------------------------------------
int main()
{
线程t[num_threads];
n=0;
对于(inti=0;icout辅助函数很短,即执行完成得很快,因此每个线程都有可能在下一个线程启动之前完成。此外,您可能需要链接到线程库以获得真正的线程,例如,
-lpthread
。即使如此,您得到的结果纯属偶然,可能出现在任何一个线程中秩序

要使程序正确同步,您需要进行两项更正。更改:

int n;
// ...
A[n] = tid; n++;


通常,最好完全避免同步问题,并在线程之间分配工作负载。因为每次迭代完成的工作在这里是相同的,所以很容易将工作平均分配:

void ThreadFunc(int tid, int first, int last)
{
    for (int i = first; i < last; i++)
        A[i] = tid;
}
void ThreadFunc(int tid,int first,int last)
{
for(int i=first;i
在main中,修改线程创建循环:

for (int first = 0, i = 0; i < num_threads; i++) {
    // possible num_threads does not evenly divide ASIZE.
    int last = (i != num_threads-1) ? std::size(A)/num_threads*(i+1) : std::size(A);
    t[i] = thread(ThreadFunc, i, first, last);
    first = last;
}
for(int first=0,i=0;i

当然,通过这样做,即使数组可能被无序写入,每次值都会存储到相同的位置。

因为
n
是从多个线程访问的,所以这些访问需要同步,以便在一个线程中所做的更改不会与在另一个线程中所做的更改冲突。至少有有两种方法可以做到这一点

首先,您可以使
n
成为一个原子变量。只需更改其定义,并在使用值的地方执行增量:

std::atomic<int> n;

...

A[n++] = tid;

这比原子访问慢得多,因此在这里不合适。在更复杂的情况下,这将是正确的解决方案。

您在
n
上有一个竞争条件,好的,我如何解决它?std::mutex可以帮助您:您希望的行为是什么?现在输出未定义。您希望用单个值填充还是刚刚赢得为什么结果不是更“分散”?如果这是第二个问题,那么没有好的答案-依赖于环境、依赖于平台等。我想知道为什么结果不是分散的。谢谢你的回答。缺少:
A[n]=tid;n++;
不是原子操作。std::atomic_int n;没有任何帮助。如果所有五个线程都以n=0同时启动,那么很容易每个线程在n=0时尝试设置一个[n]=tid,这意味着您有一个数据竞争,然后n增加五倍到n=5,因此A[1]到A[4]从未设置。或所有其他类型的效果。非常感谢您的回答!
std::atomic<int> n;

...

A[n++] = tid;
std::mutex mtx;
int next_n() {
    std::unique_lock<std::mutex> lock(mtx);
    return n++;
}
A[next_n()] = tid;