我正在玩一些 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 的新手,只是玩玩,我知道竞争条件非常危险(可能导致未定义的行为),这只是把我的手放在火里所以我可以理解它。
最佳答案
这里有几件事阻止您看到您期望的上下文切换行为:
- 线程基本上处于紧密循环中。中间不太可能发生上下文切换。
- 当
w(2)
打印6
,然后打印47
时,您的示例中确实有一个奇怪的上下文切换。它从 3 切换到 2,然后再切换回来。 - C++ 编译器可能优化了对全局变量的访问。使变量
volatile
可能会有所帮助。请注意,volatile
并不是真正的解决方案。例如,增量可能不是原子操作(也称为获取、增量、存储),而且 CPU 缓存有时会导致奇怪的伪影,因为存储到内存的操作在执行时不会被所有 CPU 看到。 - 您没有使用
endl
。通常,我认为endl
是一个绝对可怕的想法。但在这种情况下,这意味着所有写入都被缓冲,这可能会导致一些有趣的伪影。 - 此外,
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/