[英]cpp thread join if two threads rely each other should using join cause deadlock
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
std::mutex lock_bar_;
std::mutex lock_foo_;
int n = 3;
void foo() {
for (int i = 0; i < n; i++) {
lock_foo_.lock();
// printFoo() outputs "foo". Do not change or remove this line.
std::cout << "1\n";
lock_bar_.unlock();
}
}
void bar() {
for (int i = 0; i < n; i++) {
lock_bar_.lock();
// printBar() outputs "bar". Do not change or remove this line.
std::cout << "2\n";
lock_foo_.unlock();
}
}
int main(){
lock_bar_.lock();
std::thread t1{foo};
std::thread t2{bar};
t1.join(); // line 1
std::cout << "333\n"; // line 2
t2.join(); // line 3
std::cout << "3\n"; // line 4
}
結果是
1
2
1
2
1
2
333
3
或者
1
2
1
2
1
333
2
3
我的問題是:為什么這個程序可以無死鎖地運行?
join() 實際上是如何工作的?
當程序執行第 1 行時,根據 cppreference https://en.cppreference.com/w/cpp/thread/thread/join
“阻塞當前線程,直到由 *this 標識的線程完成其執行。”
我的理解是主要的 thead 應該停止。 它一直等到線程 t1 完成。 然后執行第 2 行和其余部分。 但程序似乎執行第 1 行和第 3 行。當線程 t1 完成時,它運行第 2 行。當線程 t2 完成時,它執行第 4 行。我對 join() 感到困惑。
如果有人可以提供幫助,非常感謝
第一次編輯:
忽略原程序
新程序是
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
int n = 10;
bool first = true;
std::condition_variable cv1;
std::condition_variable cv2;
std::mutex m;
void foo() {
std::unique_lock<std::mutex> ul(m, std::defer_lock);
for (int i = 0; i < n; i++) {
ul.lock();
cv1.wait(ul, [&]()->bool {return first;} );
std::cout << "1\n";
// printFoo() outputs "foo". Do not change or remove this line.
first = !first;
ul.unlock();
cv2.notify_all();
}
}
void bar() {
std::unique_lock<std::mutex> ul(m, std::defer_lock);
for (int i = 0; i < n; i++) {
ul.lock();
cv2.wait(ul, [&]()->bool {return !first;} );
// printBar() outputs "bar". Do not change or remove this line.
std::cout << "2\n";
first = !first;
ul.unlock();
cv1.notify_all();
}
}
int main(){
std::thread t1{foo};
std::thread t2{bar};
t1.join();
std::cout << "3\n";
t2.join();
}
同樣的問題
您做出了錯誤的假設,即互斥鎖可以從不同的線程鎖定和解鎖。
一個線程鎖定的互斥鎖不能被另一個線程解鎖。 整個鎖定/解鎖過程是每個線程。
lock_bar_.unlock();
第一個函數中的這一行沒有意義。 請參閱 Windows 中的ReleaseMutex (我猜它在其他操作系統中也是如此)。 它從當前線程釋放先前鎖定的互斥鎖,而不是從任何其他線程釋放。
你的線程做的工作很少。 根據您的操作系統和 cpu 內核的數量,線程只會以固定的時間間隔切換。 在t1.join
返回t2
之后, t1.join
可能已經完成執行(您的第一個輸出)。
如果您向線程中的循環添加一些睡眠,則每次都應該看到第二個輸出,因為t1.join
返回時t2
仍將執行。
請注意,從最初沒有鎖定互斥鎖的線程解鎖互斥鎖具有未定義的行為: https : //en.cppreference.com/w/cpp/thread/mutex/unlock
答案是當 std::thread t2{} 創建時,它進入隊列。 這就是為什么 t2 也被執行的原因。 join() 確實意味着 start()。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.