订单在执行
问题描述:
线程考虑一个简单的例子同意:订单在执行
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex
std::mutex mtx; // mutex for critical section
void print_block(int n, char c) {
// critical section (exclusive access to std::cout signaled by locking mtx):
mtx.lock();
for (int i = 0; i<n; ++i) { std::cout << c; }
std::cout << '\n';
mtx.unlock();
}
int main()
{
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 50, '$');
th1.join();
th2.join();
return 0;
}
是否总是保证th1
将执行for循环的第一个线程?
意思是,当我这样做:
th1.join();
th2.join();
那我可以绝对确保th1
将先执行?
答
不,你最有可能看到th1
总是首先启动,因为首先完成该变量的线程构造(并且线程构造是昂贵的),因此在之后开始。这并不意味着有订单。
调用join()
与首先执行哪个线程没有任何关系,这是在构建时完成的,当您提供可调用的代码时。
th1
可以构建,然后由操作系统停滞,然后会导致首先运行。没有订单,除非你实施一个。
考虑下面这个例子,给出了一个更公平开始到两个线程,它有时输出线程1为第一获取锁,它有时输出线2
实施例:
#include <iostream> // std::cout
#include <string> // std::string
#include <unordered_map> // std::unordered_map<K, V>
#include <thread> // std::thread
#include <mutex> // std::mutex
#include <atomic> // std::atomic<T>
std::unordered_map<std::thread::id, std::string> thread_map;
std::mutex mtx; // mutex for critical section
std::atomic<bool> go{ false };
void print_block(int n, char c)
{
while (!go) {} // prevent threads from executing until go is set.
// critical section (exclusive access to std::cout signaled by locking mtx):
mtx.lock();
std::cout << thread_map.find(std::this_thread::get_id())->second <<
" acquires the lock.\n";
mtx.unlock();
}
int main()
{
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 50, '$');
thread_map.emplace(std::make_pair(th1.get_id(), "Thread 1"));
thread_map.emplace(std::make_pair(th2.get_id(), "Thread 2"));
go.store(true);
th1.join();
th2.join();
return 0;
}
当处理并发编程时,不要对执行顺序做任何假设。相反,假设所有情况都是可能的。这使得你的代码更加可靠,反而更简单。 –
[你正在使用'std :: mutex'错误](http://kayari.org/cxx/antipatterns.html#locking-mutex),你不应该调用'std :: mutex :: lock()'和'的std ::互斥::解锁()'。相反,在'print_block()'开始时创建'std :: lock_guard <:mutex>'并让它为你锁定和解锁互斥锁。 –