2016-05-05 2 views
2

В моем многопоточном приложении я использую std::mutex для доступа к одному ресурсу несколькими потоками. Это прекрасно работает. Но в какой-то момент моего кода я должен завершить потоки, используя TerminateThread(...). Когда я начинаю нить снова (с помощью _beginthreadex), я получаю исключение, если один из потоков был в замке мьютекса, когда оно было прекращено:C++ многопотоковая блокировка мьютекса «reset»

Параллелизма :: improper_lock Bei Speicherort 0x03B4F3D0.

Это брошено в rtlocks.cpp, строка 1184 (в bool critical_section::_Acquire_lock):

LockQueueNode * pPrevious = reinterpret_cast<LockQueueNode *>(InterlockedExchangePointer(&_M_pTail, pNewNode)); 

Я думаю, если бы я мог "сбросить" семафор, я хотел бы получить исключение, верно? Как я могу это сделать?

(я использую <process.h>)

редактировать

Я попытался следующие:

std::mutex dataStorage_lock; 
mutexHandler[0] = &dataStorage_lock; //storing all mutexs in an array 

//when trying to delete: 
delete mutexHandler[0]; 

Но я получаю:

Debug Assertion Failed!

Expression: _BLOCK_TYPE_IS_VALID (pHead-> nBlockUse)

+7

рефакторинга кода так что вам не нужно прерывать потоки. Больше нечего обсуждать. –

+2

Это одна из причин, почему 'TerminateThread()' небезопасно. См. Https://blogs.msdn.microsoft.com/oldnewthing/20150814-00/?p=91811 В этой статье есть бонусное стихотворение Ларри Остермана: «Сколько раз нужно сказать: никогда не называть TerminateThread» –

ответ

5

это псевдокод, но вы должны получить идею:

неправильно:

function thread_proc(): 
    for_ever: 
    do_things 

function stop_my_thread(): 
    TerminateThread(...) 

права:

function thread_proc(): 
    while(not terminate_signal): 
    do_things 

function stop_my_thread(): 
    terminate_signal.set(); // signals the thread to terminate 
    thread.join();   // waits for the thread to terminate 
+0

Так как сигнал, я мог бы использовать нормальное булево, например. 'bool doExit'. Когда я хочу сделать поток завершающим, я устанавливаю (в моей основной функции) 'doExit = true'. Но мне понадобится еще один 'mutex' для' doExit', потому что я могу получить ошибку, когда я установил ее в true, когда она будет восстановлена ​​в условии if в потоке, не так ли? – black

+1

@black вы должны использовать либо атомный (см. 'Std :: atomic'), либо condition_variable (' std :: condition_variable'). В мире окон вы можете использовать «Событие», если вы не против быть нестандартным. Не просто используйте обычную переменную. Стандарт C++ не предлагает никаких гарантий того, что изменения, сделанные в одном потоке, будут видны в другом (это включает в себя изменчивые переменные - они не предназначены для потоковой передачи, они предназначены для ввода-вывода). –

+0

Спасибо! 'std :: atomic' работает хорошо. – black

2

Вы либо должны уничтожить семафор и создать совершенно новый, или вы можете изменить код таким образом, что во время ожидания на мьютексе поток может быть прерывается (а не прерывается). Для некоторых идей о прерывании, смотрите здесь: http://www.boost.org/doc/libs/1_54_0/doc/html/thread/thread_management.html#thread.thread_management.tutorial.interruption

+0

I не используйте boost; Я включаю process.h. Любое подобное решение? – black

+0

К вашему первому решению (уничтожению мьютекса): Есть ли что-то похожее на 'myMutex = NULL'? – black

+0

@black: Если у вас есть 'mutex * m = new mutex();' тогда вы можете позже «удалить m» и создать его снова с нуля. –

Смежные вопросы