2017-09-16 111 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

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