Lock_guard с ограниченной областью действия не освобождает мьютекс в статическом методе
Платформа Debian 9 | РУКА
У меня есть класс, который используется для хранения идентификаторов потоков в
std::list
а затем распечатать список как часть процедуры выключения. Есть два статических метода:
AddId()
а также
PrintIds()
. Поскольку статические методы используются несколькими потоками, доступ к списку защищен с помощью файла . Я столкнулся с двумя проблемами, которые поставили меня в тупик, и они могут быть связаны. Я надеюсь, что один из вас может помочь объяснить, что мне не хватает.
Обратите внимание , что я сначала использовал прицел
std::lock_guard<std::mutex>
с и временно обосновались на
std::unique_lock<std::mutex>
s, которые показаны в коде по причинам, описанным здесь.
Проблема 1. Когда программа запускается, все потоки вызывают , который добавляет идентификатор потока в список вместе со строковым именем. Кажется, это работает нормально. Однако, когда вызывается во время процедуры выключения, все еще заблокирован и блокируется. Во время тестирования я разблокировал в строке, предшествующей -- что является неопределенным поведением , если он не был заблокирован вызывающим потоком, -- и тогда все заработало, как и ожидалось. Единственное место, где используется, находится в этих двух методах, и с учетом области действия должно было быть разблокировано при каждом вызове метода. Я прошел через несколько итераций блокировки и разблокировки напрямую, используя s и т. Д. В конце концов я нашел несколько работоспособное решение, используя s, которые находятся в приведенном здесь коде. Однако и это меня озадачило.
s работают, если я использую , но только в . Если я использую
std::adopt_lock
in , то я получаю ошибку сегментации всякий раз, когда
ThreadMgr::PrintIds()
называется.
Проблема 2 Как указывалось ранее, работает нормально с любым или когда все потоки вызывают его при запуске. Однако существуют сеансы пользовательского интерфейса, в которых каждый сеанс порождает поток. Когда вызывается из одного из этих потоков сеанса, оба
std::lock_guard
а также
std::unique_lock
блокировать как
std::mutex
уже заблокирован. Так,
ThreadMgr::AddId()
отлично работает для любого другого потока, но не для потоков сеанса, которые запускаются позже.
Если есть какая-либо другая информация, которую я могу предоставить, чтобы помочь найти решение, дайте мне знать.
class ThreadMgr {
public:
ThreadMgr();
~ThreadMgr();
static void AddId(std::string);
static void PrintIds();
private:
static std::list<ThreadId> t_list;
static std::mutex list_mtx;
};
/*Definition*/
ThreadMgr::ThreadMgr() {}
ThreadMgr::~ThreadMgr() {}
/*Static Members*/
void ThreadMgr::AddId(std::string name) {
ThreadId t_id = getThreadId(name);
{
std::unique_lock<std::mutex> lock(list_mtx);
t_list.push_front(t_id);
}
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << "---Added id: " << t_id.tid << " for the " << name << " thread." << std::endl;
return;
}
void ThreadMgr::PrintIds() {
std::ostringstream oss;
oss << "\n**************************Thread Ids**************************\n";
{
std::unique_lock<std::mutex> lock(list_mtx, std::adopt_lock);
for (std::list<ThreadId>::iterator t = t_list.begin(); t != t_list.end(); t++) {
oss << "---" << t->name << " : " << t->tid << '\n';
}
}
oss << "************************End Thread Ids************************" << '\n';
std::lock_guard<std::mutex> lk(cout_mtx);
std::cout << oss.str() << std::endl;
return;
}
std::mutex ThreadMgr::list_mtx;
std::list<ThreadId> ThreadMgr::t_list;
int Main(){
ThreadMgr::AddId("Main");
std::thread MbServerT(MbServer);
std::thread UiServerT(UiServer);
while(run){
//do stuff
}
ThreadMgr::PrintIds();
if(MbServerT.joinable())
MbServerT.join();
if(UiServerT.joinable())
UiServerT.join();
return 0;
}