C++ 线程在调用 `join()` 后仍然可以连接
C++ thread still joinable after calling `join()`
我有一段代码模拟了每个提供者和消费者都是一个线程的provider/consumer场景。我已将每个消费者与一个提供者配对,消费者将等到其提供者完成(通过在提供者线程上调用 join()
),然后再执行。代码如下:
std::vector<std::thread> threads;
const uint32_t num_pairs = 3;
auto provider = [&](uint32_t idx) {
/* produce resources and put them in a global container */
};
auto consumer = [&](uint32_t idx) {
/* consumer i is paired with provider (i-num_pairs) */
uint32_t provider_idx = idx - num_pairs;
threads[provider_idx].join();
assert(threads[provider_idx].joinable() == false);
/* access the resources */
};
for (uint32_t i = 0; i < 2 * num_pairs; i++) {
if (i < num_pairs) {
/* 0, 1, 2 are providers */
threads.emplace_back(provider, i);
} else {
/* 3, 4, 5 are consumers */
threads.emplace_back(consumer, i);
}
}
/* join the consumer threads later */
大多数时候它工作正常,但有时 consumer
中的断言会失败,并且提供者线程在加入后仍然可以加入。实施不正确还是有什么我不知道发生的事情?请帮助并提前致谢!
矢量 threads
随着您将线程推入其中而增长,很有可能某些线程会在您完成添加所有线程之前开始执行。当向量容量增加时,所有迭代器和对它的引用都变得无效。这意味着在 threads[provider_idx]
中,returned 引用可能在 []
运算符的 return 和线程方法的执行之间无效。由于这是未定义的行为,因此您观察到 join
和 joinable
的不当行为并不意外。
在创建线程之前保留向量的大小应该可以解决问题:
threads.reserve(2 * num_pairs);
我有一段代码模拟了每个提供者和消费者都是一个线程的provider/consumer场景。我已将每个消费者与一个提供者配对,消费者将等到其提供者完成(通过在提供者线程上调用 join()
),然后再执行。代码如下:
std::vector<std::thread> threads;
const uint32_t num_pairs = 3;
auto provider = [&](uint32_t idx) {
/* produce resources and put them in a global container */
};
auto consumer = [&](uint32_t idx) {
/* consumer i is paired with provider (i-num_pairs) */
uint32_t provider_idx = idx - num_pairs;
threads[provider_idx].join();
assert(threads[provider_idx].joinable() == false);
/* access the resources */
};
for (uint32_t i = 0; i < 2 * num_pairs; i++) {
if (i < num_pairs) {
/* 0, 1, 2 are providers */
threads.emplace_back(provider, i);
} else {
/* 3, 4, 5 are consumers */
threads.emplace_back(consumer, i);
}
}
/* join the consumer threads later */
大多数时候它工作正常,但有时 consumer
中的断言会失败,并且提供者线程在加入后仍然可以加入。实施不正确还是有什么我不知道发生的事情?请帮助并提前致谢!
矢量 threads
随着您将线程推入其中而增长,很有可能某些线程会在您完成添加所有线程之前开始执行。当向量容量增加时,所有迭代器和对它的引用都变得无效。这意味着在 threads[provider_idx]
中,returned 引用可能在 []
运算符的 return 和线程方法的执行之间无效。由于这是未定义的行为,因此您观察到 join
和 joinable
的不当行为并不意外。
在创建线程之前保留向量的大小应该可以解决问题:
threads.reserve(2 * num_pairs);