do {
mutex.lock();
size = attemptList.size();
mutex.unlock();
if (size == 0) {
usleep(300);
}
} while (size == 0);
За исключением проблемы эффективности, этот код блокирует мьютекс, получает размер списка и разблокирует мьютекс.
Предположим, что поток пришел к выводу, что размер списка равен 1, и, следовательно, поток покидает цикл while. size
равно 1. На данный момент список имеет только одно значение. Цикл while
завершается.
Но прежде чем продолжить, один из ваших других потоков, который делает в тот же момент одно и то же, одновременно: он блокирует мьютекс, получает размер списка, разблокирует мьютекс, определяет, что размер список равен 1 и тоже выходит из цикла while, как и первый поток. Давайте посмотрим, что будет дальше, с обоими нашими потоками в данный момент:
while(size != 0) {
mutex.lock();
password = attemptList.front();
attemptList.pop_front();
Хорошо, теперь первый поток просыпается, входит в цикл while, блокирует мьютекс, захватывает единственную запись в списке, удаляет ее из списка, и список теперь пуст.
Ваш второй поток теперь делает то же самое и блокирует свой вызов mutex.lock()
, потому что первый поток заблокировал его.
Первый поток в конечном итоге разблокирует мьютекс. Второй поток теперь продолжается; он заблокировал мьютекс и работает в иллюзии, что список не пустой, потому что он все еще думает, что его размер равен 1 (потому что это был тот момент, когда он его заблокировал), в начальном цикле while
и пытается удалить первый элемент из пустого списка.
Неопределенное поведение.
Это причина вашего сбоя.