好的@Ali,讓我們簡單介紹一些事情(術語)。
namespace std
- 是一個簡單的命名空間,如:
namespace my_namespace {
int my_integer;
};
包含噸有用的類的程序員,通過超過於強大的人寫的,而且,你知道它應該是儘可能靈活(後來的「聲明1「),casue不同的人有不同的需求。
當然,它遵守C++標準的一般規則,因爲它的內容也是。
現在讓我們來談談您想要的std::thread
。
其簡單的類代表a single thread of execution。它可以讓你execue在「外太空」的功能,並與我們的抽象的「外太空」保持聯繫,還處理了一些數據:
- _id - 線程ID
- _handle - 祕密變量,它是主要用於與「外太空」
- ,當然它使一些數據 關於執行的狀態(是否有任何實體現在執行某處 的「外太空」,其中的關鍵使我們)
如果你看起來some references在更多的細節,並牢記我們的「聲明1」,你會發現如下信息:
- 「
std::thread
對象也可以是不代表任何線程狀態」
- 「沒有兩個
std::thread
對象可以表示相同的執行線程; std::thread
不是CopyConstructible或CopyAssignable,雖然它是MoveConstructible和MoveAssignable。「
現在你應該得出一個結論,即std::thread
變量和執行實體是分開的,但試圖刪除附加到一個執行實體std::thread
變量拋出異常。
但當實體執行結束,std::thread
變量保持活着,並且可以連接到任何其他實體
爲theese需要有以下方法:
join() // waits for a thread to finish its execution
// if it is attached to something, the code execution will not go futher until our entity finishes its execution.
detach() // permits the thread to execute independently from the thread handle
// detaches our std:: thread variable from executing entity, now our entity lives its own life. std::thread variable may be removed while the entity keeps alive
joinable() // checks whether the thread is joinable, i.e. potentially running in parallel context
// if thread is attached to something which is executing now, it returns true, otherwise false
這裏是一些代碼示例,將清除出你的誤解:
#include <iostream>
#include <thread>
#include <chrono>
using namespace::std;
void some_func1() {
cout << "some_func1 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func1 thread finished " << endl;
}
void some_func2() {
cout << "some_func2 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func2 thread finished " << endl;
}
int main() {
thread some_thread;
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread = thread(some_func1);
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread.detach();
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
this_thread::sleep_for(chrono::seconds(1));
some_thread = thread(some_func2);
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
some_thread.join();
cout << "Is some_thread joinable: " << some_thread.joinable() << endl;
}
// Output is:
// Is some_thread joinable: 0
// some_func1 thread started
// Is some_thread joinable: 1
// Is some_thread joinable: 0
// some_func2 thread started
// Is some_thread joinable: 1
// some_func1 thread finished
// some_func2 thread finished
// Is some_thread joinable: 0
// Press any key to continue . . .
如果你想確保,你的實體執行完畢的線程變量刪除之前,你可以把它包在另一個類中,並在析構函數中調用join()
,正如你提到的那樣。
或者你也可能把它包裝在另一個將在析構函數中調用detach()
。
這兩種方式可以防止你大量的粉碎。
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
typedef void Myfunc();
void some_func1() {
cout << "some_func1 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func1 thread finished " << endl;
}
void some_func2() {
cout << "some_func2 thread started " << endl;
this_thread::sleep_for(chrono::seconds(2));
cout << "some_func2 thread finished " << endl;
}
class ICareAboutThread {
std::thread thread_;
public:
ICareAboutThread(Myfunc f = nullptr) : thread_(f) {};
~ICareAboutThread() { join(); }
bool joinable() { return thread_.joinable();}
void join() { thread_.join();}
void detach() { thread_.detach();}
// other constructors : move , safe copying - if necessary;
};
class IDontCareAboutThread {
std::thread thread_;
public:
IDontCareAboutThread(Myfunc f = nullptr) : thread_(f) {};
~IDontCareAboutThread() { detach(); }
bool joinable() { return thread_.joinable(); }
void join() { thread_.join(); }
void detach() { thread_.detach(); }
// other constructors : move , safe copying - if necessary;
};
int main() {
ICareAboutThread i_care(some_func1);
this_thread::sleep_for(chrono::seconds(1));
IDontCareAboutThread i_dont_care(some_func2);
return 0;
}
// Output is:
// some_func1 thread started
// some_func2 thread started
// some_func1 thread finished
// Press any key to continue . . .
現在我希望它的晶瑩剔透你,如果你瞭解當變量刪除:d
有沒有區別 – Justin
我覺得你過於簡單化和歪曲。如果你編寫自己的代碼,那麼*你*可以決定在你的情況下加入析構函數是否合適。但是,這並不意味着加入析構函數總是適合每個*情況下的每個用戶。在自動加入是一個問題的情況下,你當然會*不*使用加入包裝。 –
你鏈接的答案實際上並不是說在析構函數中調用'join'。它表示將線程包裝在另一個類中,「這將在銷燬時具有期望的行爲」。如果您希望加入的行爲,並且涉及到的折衷方案可以,您可以這樣做。它不會解決在析構函數中調用'join'的問題,答案並不會聲稱它會。 – user2357112