По логике ведь в данном случае на первом lock мьютекс должен заблокироваться, а на втором lock программа должна ждать пока он будет разблокирован, чтобы снова его заблокировать
Я ничего не путаю?
По сути если два раза подряд вызвать lock, то программа должна зависнуть, но не должно же вываливаться исключение? Или это какая-то система защиты от мертвой блокировки? Если так, то как ее обойти?
If lock is called by a thread that already owns the mutex, the behavior is undefined: for example, the program may deadlock. An implementation that can detect the invalid usage is encouraged to throw a std::system_error with error condition resource_deadlock_would_occur instead of deadlocking.
Для этого есть join у потоков, пихаешь их в массив и дожидаешься завершения всех. А вообще для сетевых запросов лучше использовать асинхронность, а не потоки.