<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 線程(thread) 線程(譯注:大約是C++11中最激動人心的特性了)是一種對程序中的執行或者計算的表述。跟許多現代計算一樣,C++11中的線程之間能夠共享地址空間。從這點上來看,它不同于進程:進程一般不會直接跟其它進程共享數據。在過去,C++針對不同的硬件和操作系統有著不同的線程實現版本。如今,C++將線程加入到了標準件庫中:一個標準線程ABI。 許多大部頭書籍以及成千上萬的論文都曾涉及到并發、并行以及線程。在這一條FAQ里幾乎不涉及這些內容。事實上,要做到清楚地思考并發非常難。如果你想編寫并發程序,請至少看一本書。不要依賴于一本手冊、一個標準或者一條FAQ。 在用一個函數或者函數對象(包括lambda)構造std::thread時,一個線程便啟動了。 ``` #include <thread> void f(); struct F { void operator()(); }; int main() { std::thread t1{f}; // f() 在一個單獨的線程中執行 std::thread t2{F()}; // F()() 在一個單獨的線程中執行 } ``` 然而,無論f()和F()執行任何功能,都不能給出有用的結果。這是因為程序可能會在t1執行f()之前或之后以及t2執行F()之前或之后終結。我們所期望的是能夠等到兩個任務都完成,這可以通過下述方法來實現: ``` int main() { std::thread t1{f}; // f() 在一個單獨的線程中執行 std::thread t2{F()}; // F()()在一個單獨的線程中執行 t1.join(); // 等待t1 t2.join(); // 等待t2 } ``` 上面例子中的join()保證了在t1和t2完成后程序才會終結。這里”join”的意思是等待線程返回后再終結。 通常我們需要傳遞一些參數給要執行的任務。例如: ``` void f(vector<double>&); struct F { vector<double>& v; F(vector<double>& vv) :v{vv} { } void operator()(); }; int main() { // f(some_vec) 在一個單獨的線程中執行 std::thread t1{std::bind(f,some_vec)}; // F(some_vec)() 在一個單獨的線程中執行 std::thread t2{F(some_vec)}; t1.join(); t2.join(); } ``` 上例中的標準庫函數bind會將一個函數對象作為它的參數。 通常我們需要在執行完一個任務后得到返回的結果。對于那些簡單的對返回值沒有概念的,我建議使用std::future。另一種方法是,我們可以給任務傳遞一個參數,從而這個任務可以把結果存在這個參數中。例如: ``` void f(vector<double>&, double* res); // 將結果存在res中 struct F { vector<double>& v; double* res; F(vector<double>& vv, double* p) :v{vv}, res{p} { } void operator()(); //將結果存在res中 }; int main() { double res1; double res2; // f(some_vec,&res1) 在一個單獨的線程中執行 std::thread t1{std::bind(f,some_vec,&res1)}; // F(some_vec,&res2)() 在一個單獨的線程中執行 std::thread t2{F(some_vec,&res2)}; t1.join(); t2.join(); std::cout << res1 << " " << res2 << ‘\n’; } ``` 但是關于錯誤呢?如果一個任務拋出了異常應該怎么辦?如果一個任務拋出一個異常并且它沒有捕獲到這個異常,這個任務將會調用std::terminate()。調用這個函數一般意味著程序的結束。我們常常會為避免這個問題做諸多嘗試。std::future可以將異常傳送給父線程(這正是我喜歡future的原因之一)。否則,返回錯誤代碼。 除非一個線程的任務已經完成了,當一個線程超出所在的域的時候,程序會結束。很明顯,我們應該避免這一點。 沒有辦法來請求(也就是說盡量文雅地請求它盡可能早的退出)一個線程結束或者是強制(也就是說殺死這個線程)它結束。下面是可供我們選擇的操作: * 設計我們自己的協作的中斷機制(通過使用共享數據來實現。父線程設置這個數據,子線程檢查這個數據(子線程將會在該數據被設置后很快退出))。 * 使用thread::native_handle()來訪問線程在操作系統中的符號 * 殺死進程(std::quick_exit()) * 殺死程序(std::terminate()) 這些是委員會能夠統一的所有的規則。特別地,來自POSIX的代表強烈地反對任何形式的“線程取消”。然而許多C++的資源模型都依賴于析構器。對于每種系統和每種可能的應有并沒有完美的解決方案。 線程中的一個基本問題是數據競爭。也就是當在統一地址空間的兩個線程獨立訪問一個對象時將會導致沒有定義的結果。如果一個(或者兩個)對對象執行寫操作,而另一個(或者兩個)對該對象執行讀操作,兩個線程將在誰先完成操作方面進行競爭。這樣得到的結果不僅僅是沒定義的,而且常常無法預測最后的結果。為解決這個問題,C++0x提供了一些規則和保證從而能夠讓程序員避免數據競爭。 * C++標準庫函數不能直接或間接地訪問正在被其它線程訪問的對象。一種例外是該函數通過參數(包括this)來直接或間接訪問這個對象。 * C++標準庫函數不能直接或間接修改正在被其它線程訪問的對象。一種例外是該函數通過非const參數(包括this)來直接或間接訪問這個對象。 * C++標準函數庫的實現需要避免在同時修改統一序列中的不同成員時的數據競爭。 除非已使用別的方式做了聲明,多個線程同時訪問一個流對象、流緩沖區對象,或者C庫中的流可能會導致數據競爭。因此除非你能夠控制,絕不要讓兩個線程來共享一個輸出流。 你可以 * 等待一個線程[一定的時間](http://chenlq.net/chinese-version-of-c-0-x-faq-time-utility.html) * 通過[互斥](http://chenlq.net/cpp11-faq-chinese-version-series-exclusive.html)來控制對數據的訪問 * 通過[鎖來控制對數據的訪問](http://chenlq.net/c-0-x-faq-chinese-version-lock.html) * 使用[條件變量](http://chenlq.net/chinese-version-of-c-11-faq-condition-variable.html)來等待另一個線程的行為 * 通過[future](http://chenlq.net/c-0-x-faq-chinese-version-std-future-and-the-the-std-promise.html)來從線程中返回值 同時可參考: * Standard: 30 Thread support library [thread] * 17.6.4.7 Data race avoidance [res.on.data.races] * ??? * H. Hinnant, L. Crowl, B. Dawes, A. Williams, J. Garland, et al.: [Multi-threading Library for Standard C++ (Revision 1)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2320.html) N2497==08-0007 * H.-J. Boehm, L. Crowl: C++ object lifetime interactions with the threads API N2880==09-0070. * L. Crowl, P. Plauger, N. Stoughton: Thread Unsafe Standard Functions N2864==09-0054. * WG14: [Thread Cancellation](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2455.pdf) N2455=070325. (翻譯:Yibo Zhu)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看