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_lockin , то я получаю ошибку сегментации всякий раз, когда 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;
}

0 ответов

Другие вопросы по тегам