我很少考虑两个连续表达式之间的情况,对函数的调用与其主体的第一个表达式的执行之间,或者对构造函数的调用与其初始化器的执行之间发生了什么。然后我开始读关于并发的文章..。
1.)在两个连续调用具有相同可调用性的std::thread构造函数(例如函数、函子、lambda)中,其主体以同一个std::mutex对象的std::lock_guard初始化开始,标准是否保证与第一个thread构造函数调用对应的线程首先执行受锁保护的代码?
2.)如果标准没有提供保证,那么与第二个thread构造函数调用对应的线程是否有可能首先执行受保护的代码?(例如,在执行第一个thread构造函数调用的初始化程序或主体时,系统负载很重)
下面是一个全局std::mutex对象m和一个初始化为1的全局unsigned num。函数foo的开式大括号{和std::lock_guard之间只有空格。在main中,有两个std::thread的t1和t2。t1首先调用线程构造函数。t2调用线程构造函数。每个线程都使用指向foo的指针构造。t1用unsigned参数1调用foo。t2用unsigned参数2调用foo。根据哪个线程首先锁定mutex,在两个线程执行了受锁保护的代码之后,num的值要么是4,要么是3。如果num在锁上击败t2,则t1将等于t2。否则,num将等于3。我在每个循环的末尾循环并将num重置为1,对此我进行了100,000个试验。(据我所知,结果并不是也不应该取决于哪个线程首先被join()编辑。)
#include <thread>
#include <mutex>
#include <iostream>
std::mutex m;
unsigned short num = 1;
void foo(unsigned short par) {
std::lock_guard<std::mutex> guard(m);
if (1 == num)
num += par;
else
num *= par;
}
int main() {
unsigned count = 0;
for (unsigned i = 0; i < 100000; ++i) {
std::thread t1(foo, 1);
std::thread t2(foo, 2);
t1.join();
t2.join();
if (4 == num) {
++count;
}
num = 1;
}
std::cout << count << std::endl;
}最后,count等于100000,所以每次t1都赢了比赛。但这些试验证明不了什么。
3.)标准任务“首先调用thread构造函数”是否始终意味着“首先调用传递给thread构造函数的可调用性”?
4.)标准任务“首先调用传递给thread构造函数的可调用性”是否始终意味着“首先锁定mutex”;如果在可调用的主体中不存在依赖于传递给可调用的参数的代码,该参数在进行std::lock_guard初始化之前传递给可调用的行?(还排除了任何可调用的本地static变量,如调用次数的计数器,这些计数器可用于故意延迟某些调用。)
发布于 2014-01-11 01:23:53
https://stackoverflow.com/questions/21057231
复制相似问题