Ответ 1
Теперь я понимаю, что точка Mutex - это предотвращение одновременного доступа двух потоков к одному и тому же ресурсу, но я не вижу корреляции между io_mutex и std:: cout.
std::cout
является глобальным объектом, поэтому вы можете видеть это как общий ресурс. Если вы обращаетесь к нему одновременно из нескольких потоков, эти обращения должны быть синхронизированы каким-то образом, чтобы избежать расследований данных и поведения undefined.
Возможно, вам будет легче заметить, что одновременный доступ происходит, считая, что:
std::cout << x
Фактически эквивалентно:
::operator << (std::cout, x)
Это означает, что вы вызываете функцию, которая работает с объектом std::cout
, и вы делаете это из разных потоков одновременно. std::cout
должен быть каким-то образом защищен. Но это не единственная причина, по которой существует scoped_lock
(продолжайте читать).
Этот код просто блокирует все в пределах области действия до тех пор, пока область действия не будет закончена?
Да, он блокирует io_mutex
, пока сам объект блокировки не выходит из области видимости (являющийся типичной оберткой RAII), которая происходит в конце каждой итерации цикла for.
Зачем это нужно? Ну, хотя в С++ 11 отдельные вставки в cout
гарантируются как потокобезопасные, последующие, отдельные вставки могут чередоваться, когда несколько потоков выводят что-то.
Имейте в виду, что каждая вставка через operator <<
является отдельным вызовом функции, как если бы вы делали:
std::cout << id;
std::cout << ": ";
std::cout << i;
std::cout << endl;
Тот факт, что operator <<
возвращает объект stream, позволяет вам связать вышеуказанные вызовы функций в одном выражении (как это было в вашей программе), но факт, что вы выполняете несколько отдельных вызовов функций, сохраняется.
Теперь, смотря на вышеприведенный фрагмент, более очевидно, что цель этой блокировки с привязкой состоит в том, чтобы убедиться, что каждое сообщение формы:
<id> ": " <index> <endl>
Получает печать без части, чередующихся с частями от других сообщений.
Кроме того, в С++ 03 (где вставки в cout
не гарантируются потокобезопасностью), блокировка будет защищать сам объект cout
от доступа одновременно.