Ускорение блокировки Mutex - программирование
Подтвердить что ты не робот

Ускорение блокировки Mutex

Я читал учебник Boost Mutex на drdobbs.com и нашел этот фрагмент кода:

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost::mutex io_mutex;

void count(int id)
{
  for (int i = 0; i < 10; ++i)
  {
    boost::mutex::scoped_lock
      lock(io_mutex);
    std::cout << id << ": " <<
      i << std::endl;
  }
}

int main(int argc, char* argv[])
{
  boost::thread thrd1(
    boost::bind(&count, 1));
  boost::thread thrd2(
    boost::bind(&count, 2));
  thrd1.join();
  thrd2.join();
  return 0;
}

Теперь я понимаю, что точка Mutex - это предотвращение одновременного доступа двух потоков к одному и тому же ресурсу, но я не вижу корреляции между io_mutex и std:: cout. Этот код просто блокирует все в пределах области действия до завершения области?

4b9b3361

Ответ 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 от доступа одновременно.

Ответ 2

Мьютекс не имеет ничего общего с чем-либо еще в программе (за исключением условной переменной), по крайней мере, на более высоком уровне. Мьютекс имеет два эффекта: он контролирует поток программы и предотвращает несколько потоков от выполнения одного и того же блока кода одновременно. Он также обеспечивает синхронизацию памяти. важной проблемой здесь является то, что мьютексы не связаны с ресурсов и не препятствовать доступу двух потоков к одному и тому же ресурс в то же время. Мьютекс определяет критический раздел кода, который может вводиться только одним потоком за раз. Если все использование конкретного ресурса осуществляется в критических разделы, управляемые одним и тем же мьютексом, тогда ресурс эффективно защищенных мьютексом. Но отношения установленный кодером, путем обеспечения того, чтобы все использование место в критических разделах.