【问题标题】:Boost threading/mutexs, why does this work?提升线程/互斥锁,为什么会这样?
【发布时间】:2011-02-28 02:26:25
【问题描述】:

代码:

#include <iostream>
#include "stdafx.h"
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>

using namespace std;
boost::mutex mut;
double results[10];

void doubler(int x) {
//boost::mutex::scoped_lock lck(mut);
 results[x] = x*2;
}

int _tmain(int argc, _TCHAR* argv[])
{
 boost::thread_group thds;
 for (int x = 10; x>0; x--) {
  boost::thread *Thread = new boost::thread(&doubler, x);
  thds.add_thread(Thread);
 }

 thds.join_all();

 for (int x = 0; x<10; x++) {
  cout << results[x] << endl;
 }

 return 0;
}

输出:

0
2
4
6
8
10
12
14
16
18
按任意键继续 。 . .

所以...我的问题是为什么这个工作(据我所知,我运行了大约 20 次)产生上述输出,即使锁定已被注释掉? 我认为总体思路是:

在每个线程中: 计算 2*x 将结果复制到 CPU 寄存器 将计算存储在数组的正确部分 将结果复制回主(共享)内存

我认为在几乎完美的条件下,这将导致结果数组的某些部分具有 0 值。它只是将数组所需的双精度复制到 cpu 寄存器吗?还是在将结果写回内存之前,计算量太少而无法被抢占?谢谢。

【问题讨论】:

    标签: c++ multithreading boost mutex


    【解决方案1】:

    该赋值在左侧有一个double 类型的左值,并且该左值是线程访问的唯一对象。由于每个线程访问不同的对象,因此没有数据竞争。

    请注意,下标数组并不构成访问。

    【讨论】:

    • @Flamewires:只要每个线程只作用于自己的结构(如数组中),复杂的数据结构就可以了。如果您翻转整数上的位,您将需要锁定或确保您具有原子读取和设置。在这种简单的情况下,这将迫使所有线程串行操作,并高度争用锁,使其成为并行化的非常糟糕的候选者。
    • 是的,如果您将 double 替换为其他类型,它仍然可以。就 C++0x 而言,没有最小大小(由实现决定是否在所有平台上工作)。如果你开始摆弄比特,你会得到一个数据竞争(因此是未定义的行为),因为你会在没有同步的情况下从多个线程访问同一个对象。
    • 嗯...你说没有最小尺寸,但是,如果我错了,请纠正我,我不能只在一个数组中分配 100 位并让它们成为单独的对象,我的也是大小限制是最小的 c++ 原语的大小?
    • 或者它会是我的计算机定义为 WORD 的任何内容吗?
    • 嗯,位不是 C++ 对象,您不能真正“分配 100 位”。最小的对象是 char 类型,如果你将类型从 double 更改为 char 并让每个线程访问不同的 char,你将不会出现竞争。
    【解决方案2】:

    由于thds.join_all(); 行,它可以工作。主执行线程在这里陷入陷阱,直到所有其他线程都完成,然后继续打印出数组。因此,您知道所有数组值在打印之前都已存储。如果你注释掉这一行,你会得到不可预知的结果。

    【讨论】:

    • 这是否会导致所有线程按顺序执行?我认为 join all 只需要所有线程在继续之前终止,无论它们在执行时对结果数组做了什么。我仍然不明白为什么没有比赛条件。
    • @Flamewires:不存在竞争条件,因为主线程显式等待其他工作线程“赶上”,从而消除了竞争条件。此外,由于每个工作线程只更新内存中特定分配的位置,因此无需担心数据。因此,所有工作线程都在主线程等待时完成它们的工作(为其预定义的内存位置分配一个值)。当所有工作人员都完成后,主线程继续。因此工作人员并行工作,但 join_all() 调用会创建一个序列点,以确保所有数据都处于良好状态。
    • 是的,我明白这一点,但如果每个都被分配,比如说,一个整数位?而不是数组中的双精度数?你明白我在说什么吗?肯定会存在竞争条件,因为要访问该位,整个 int 将被复制、更新,然后同时被 X 个线程替换。我可以指定且不会导致竞争条件的内存位置大小的下限是多少?一句话?
    • @Flamewires:使用这些位,您将需要某种锁定,它会强制所有线程串行操作。您的最低情况是您可以执行的任何原子操作。在这里,您需要执行原子读取和设置操作,或者(更可怕的是)使用某种互斥锁。
    • 好的。谢谢。我想我得到了我想要的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 2012-12-25
    • 2013-01-31
    • 1970-01-01
    相关资源
    最近更新 更多