c++ - Boost Threads - 赛车

标签 c++ multithreading boost

我正在玩一些 Boost 线程,我编写了以下代码:

#include <boost/thread.hpp>
#include <iostream>

volatile int threads = 0;

const int iterations = 200;

volatile char output[iterations*4];
volatile int k = 0;

void w() {
    threads++;
    for (int i = 0; i < iterations; i++) {
        k++;
        output[k] = '0';
    }
}
void y() {
    threads++;
    for (int i = 0; i < iterations; i++) {
        k++;
        output[k] = '1';
    }
}

int main(int argc, char* argv[]) {
    boost::thread a(&w);
    boost::thread b(&w);
    boost::thread c(&y);
    boost::thread d(&y);

    while (k <= iterations * 4) {}

    for (int i=0; i < k; i++) {
        std::cout << output[i];
    }
    return 0;
}

我不明白的是为什么这些线程的完成看起来像是在等待彼此,这在输出中显示:

000000000000000000000000000000000000000011111111

我的印象是输出是随机顺序的,语句输出类似于以下内容(预期输出):

00100000111001000000010001111100000000011111111

相反,它们紧随其后,全为 0,然后全为 1(反之亦然)。

这是为什么?在这一点上,线程似乎更像是以随机顺序堆叠,但仍然连接在一起;即在执行之前互相等待。我实际上希望 threads++ 代码可能在某些线程中同时运行,并为它们留下一些 thisthread 值。

免责声明:我是 Boost:threads 的新手,只是玩玩,我知道竞争条件非常危险(可能导致未定义的行为),这只是把我的手放在火里所以我可以理解它。

最佳答案

这里有几件事阻止您看到您期望的上下文切换行为:

  1. 线程基本上处于紧密循环中。中间不太可能发生上下文切换。
  2. w(2) 打印 6,然后打印 47 时,您的示例中确实有一个奇怪的上下文切换。它从 3 切换到 2,然后再切换回来。
  3. C++ 编译器可能优化了对全局变量的访问。使变量 volatile 可能会有所帮助。请注意,volatile 并不是真正的解决方案。例如,增量可能不是原子操作(也称为获取、增量、存储),而且 CPU 缓存有时会导致奇怪的伪影,因为存储到内存的操作在执行时不会被所有 CPU 看到。
  4. 您没有使用endl。通常,我认为 endl 是一个绝对可怕的想法。但在这种情况下,这意味着所有写入都被缓冲,这可能会导致一些有趣的伪影。
  5. 此外,cout 将是线程安全的,实现这一点所需的锁也可能会影响线程上下文相互切换的方式。

其中的一些问题可以通过直接调用write 系统调用来解决。这将强制执行系统调用,这可能会给另一个线程运行的机会。它还将强制输出恰好在执行它的代码时发生。

这是一个程序,它将展示您在多核 Unix 机器上寻找的行为。它还将向您显示 k 的最终值,以说明为什么 volatile 并不是真正的解决方案,以及它如何在值 k 上引发竞争。我最初只是建议将其作为 hack 来让您的程序更好地工作以产生您正在寻找的行为,因为在您的原始程序中它并不重要:

#include <boost/thread.hpp>
#include <iostream>
#include <unistd.h>

volatile int threads = 0;

const int iterations = 200;

volatile int k = 0;

void w(char thid) {
    threads++;
    for (int i = 0; i < iterations; i++) {
        k++;
        ::write(1, &thid, 1);
    }
}

int main(int argc, char* argv[]) {
    boost::thread a(&w, '0');
    boost::thread b(&w, '1');
    boost::thread c(&w, '2');
    boost::thread d(&w, '3');

    a.join();
    b.join();
    c.join();
    d.join();
    ::write(1, "\n", 1);
    // In general, do not mix write to stdout and cout. In this case
    // it will work, but this is a very limited and specific case.
    ::std::cout << "k == " << k << "\n";
    return 0;
}

关于c++ - Boost Threads - 赛车,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4848124/

相关文章:

c++ - boost::interprocess 共享内存 : how to have multiple different shared memory on same machine

c++ - 我如何可靠地判断 boost 线程是否已退出其 run 方法?

c++ - 无法理解 C++ 中列表的实现

c++ - Variadic 模板模拟 "runtime"扩展

c# - 当 ThreadB Monitor.Pulse(_locker) 哪个线程会先得到 _locker?

java - 在Java中重写进程类

c++ - 如何更新迭代(for 循环)求解器中的粒子位置

c++ - 玩家移动时,GameBoy Advance对象未显示在正确的位置

.net - .Net 中的进程分配

c++ - boost::future .then() 继续返回 boost::future