2017-09-16 150 views
-3

我想從程序中刪除一個死鎖。問題在於程序不斷給我中止。重點是將數據寫入文件。但是當發生死鎖時,線程應該等待,並在稍後繼續而不是中止。C++線程死鎖互斥鎖異常終止

#include <iostream> 
#include <unistd.h> 
#include <fstream> 
#include <vector> 
#include <thread> 
#include <mutex> 
#include <exception> 
#include <condition_variable> 

using namespace std; 

std::mutex mtx; 
ofstream myfile; 
condition_variable cv; 

void lock() 
{ 
    mtx.lock(); 
} 

void unlock() 
{ 
    mtx.unlock(); 
} 

void writeToFile(int threadNumber){ 
myfile << "["; 
    for(int j =1; j <= 10; j++){ 
     int num = j * threadNumber; 
     string line = std::to_string(num) + " "; 
     myfile << line; 
    } 
    myfile << "]"; 
//mtx.unlock(); 
} 

void threadFunction(int threadNumber) 
{ 
// int x = 0; 
// int y = 0; 

    try{ 
    lock(); 
    if (threadNumber % 2 == 0) 
     sleep(rand() % 4 + 1); 
    writeToFile(threadNumber); 
    throw exception(); 
    unlock(); 
    } 
    catch(...){ 
    cout << "Something went wrong!" << endl; 
    throw exception(); 
    } 
} 


int main (int argc, char const *argv[]) { 
myfile.open ("mutex.txt"); 
    std::set_terminate([](){ 
    std::cout << "Unhandled exception\n"; 
    // Here I want to fix the deadlock if something goes wrong. But I keep getting Abroted 

    }); 
     int len; 
     cout << "Enter Number of threads : "; 
     cin >> len; 
     std::thread t[len + 1]; 
     for(int i =1; i <= len;i++){ 
      t[i] = std::thread(threadFunction, i); 
      cout << "Created Thread : " <<t[i].get_id()<<endl; 
      } 

      for(int i =1; i <= len;i++){ 
      t[i].join(); 
      } 
     myfile.close(); 
     return 0; 
} 

輸出

Enter Number of threads : 5 
Created Thread : 1992414288 
Created Thread : 1982854224 
Created Thread : 1974465616 
Created Thread : 1966077008 
Created Thread : 1957688400 
Something went wrong! 
Unhandled exception 
Aborted 

我怎樣才能避免流產,讓線程等待。

更新:包括所有相關的代碼...

+0

發生死鎖時,*所有相關線程都被阻塞,等待對方,並且* none *可以繼續,*按照定義*。你的問題沒有意義。任何死鎖情況的解決方案都是始終以相同的順序獲取鎖。 – EJP

+0

你沒有得到一個關於'mtx.unlock()'的大警告,告訴你「代碼永遠不會被執行。」 ?如果沒有,請打開編譯器警告。 – WhozCraig

+0

不,我沒有得到警告 –

回答

2

沒有手動lock()/unlock()互斥做的。這很容易出錯。改爲使用guards。拋出異常後的mtx.unlock();將不會被調用。

這裏是你的代碼應該是什麼樣子:

try{ 
    std::lock_guard<std::mutex> lock(mtx); 
    if (threadNumber % 2 == 0) 
     sleep(rand() % 4 + 1); 
    writeToFile(threadNumber); 
    throw exception(); 
    } 
    catch(...){ 
    cout << "Something went wrong!" << endl; 
    throw exception(); 
    } 

爲了避免死鎖普遍認爲鎖定和多個互斥鎖解鎖需要以相反的順序來完成。因此,如果一個線程使用類似於

{ 
    std::lock_guard<std::mutex> lock1(mtx1); 
    std::lock_guard<std::mutex> lock2(mtx2); 
    // ... exception thrown somewhere 
} 

std::lock_guard的析構函數都保證在這些構建相反的順序被稱爲這個保證。

+0

那麼你是說我無法通過使用鎖定/解鎖手動修復它 –

+0

@johnS這不完全是我說的。你可以在'catch'主體中調用unlock。雖然這很容易出錯。 – user0042

+0

我想了解它是如何工作的,因此該方法 –