刚开始使用C ++ 11线程库进行多线程处理(以及一般的多线程处理),并编写了一小段短代码。
#include <iostream>
#include <thread>
int x = 5; //variable to be effected by race
//This function will be called from a thread
void call_from_thread1() {
for (int i = 0; i < 5; i++) {
x++;
std::cout << "In Thread 1 :" << x << std::endl;
}
}
int main() {
//Launch a thread
std::thread t1(call_from_thread1);
for (int j = 0; j < 5; j++) {
x--;
std::cout << "In Thread 0 :" << x << std::endl;
}
//Join the thread with the main thread
t1.join();
std::cout << x << std::endl;
return 0;
}
由于两个线程之间的竞争,每次(或几乎每次)我都希望得到不同的结果。但是,输出始终为:0
,即两个线程像顺序运行一样运行。为什么我得到相同的结果,有没有办法模拟或强制两个线程之间的竞争?
答案 0 :(得分:8)
您的样本量相当小,并且在连续标准冲洗时有些自我停顿。简而言之,你需要一把更大的锤子。
如果您想要查看真实的竞赛条件,请考虑以下事项。我故意添加了一个原子和非原子计数器,将两者都发送到样本的线程。一些测试运行结果发布在代码之后:
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
void racer(std::atomic_int& cnt, int& val)
{
for (int i=0;i<1000000; ++i)
{
++val;
++cnt;
}
}
int main(int argc, char *argv[])
{
unsigned int N = std::thread::hardware_concurrency();
std::atomic_int cnt = ATOMIC_VAR_INIT(0);
int val = 0;
std::vector<std::thread> thrds;
std::generate_n(std::back_inserter(thrds), N,
[&cnt,&val](){ return std::thread(racer, std::ref(cnt), std::ref(val));});
std::for_each(thrds.begin(), thrds.end(),
[](std::thread& thrd){ thrd.join();});
std::cout << "cnt = " << cnt << std::endl;
std::cout << "val = " << val << std::endl;
return 0;
}
从上面的代码中运行了一些示例:
cnt = 4000000
val = 1871016
cnt = 4000000
val = 1914659
cnt = 4000000
val = 2197354
请注意,原子计数器是准确的(我在具有超线程的双核i7 macbook air笔记本电脑上运行,所以4x线程,因此400万)。对于非原子计数器也不能这样说。
答案 1 :(得分:3)
第二个线程将会有很大的启动开销,所以它的执行几乎总是在第一个线程完成for循环后开始,相比之下,几乎没有时间。要查看竞争条件,您需要运行花费更长时间的计算,或者包括需要花费大量时间的i / o或其他操作,以便两个计算的执行实际上重叠。