[БЕЗ_ЗВУКА] Когда мы в «Красном поясе по C++» изучали с вами многопоточность, мы говорили, что в многопоточных программах возможны ситуации «гонки». Я напомню, что гонка — это ситуация, когда несколько потоков обращаются к одной и той же переменной, и минимум один из этих потоков эту переменную изменяет. Опасность ситуации гонки заключается в том, что она может привести к нарушению целостности данных и некорректной работе программы. Чтобы защититься от возникновения гонки, нужно выполнять синхронизацию. Об этом мы с вами также говорили в «Красном поясе по C++». Синхронизация в C++ выполняется с помощью специального класса mutex, который гарантирует так называемое взаимное исключение и обеспечивает ситуацию, в которой не более одного потока обращается к разделяемой переменной. Код, защищаемый mutex'ом, называется «критической секцией». И в «Красном поясе» мы с вами посмотрели, что чем больше размер критической секции, тем медленнее работает наша многопоточная программа. Давайте с вами рассмотрим решение задачи исследования блогов, которая у была нас в «Красном поясе по C++» как раз в блоке про многопоточность. Здесь, в этой задаче нужно было написать ExploreKeyWords, которая исследовала текст из входного потока и проверяла, какие слова из него входят в множество ключевых слов. Сейчас нам надо обратить внимание на то, что функция ExploreKeyWords вот здесь вот создает потоки с помощью вызова функции async, она создает потоки, и в каждом из этих потоков она вызывает функцию ExploreBatch, передавая в эту функцию по ссылке вот этот вот наш словарь key_words, словарь ключевых слов. Давайте посмотрим, как устроена функция ExploreBatch. Она, на самом деле, просто перебирает вектор строк текста и для каждой строки вызывает функцию ExploreLine, в которую также передает наш словарь ключевых слов. Заходим в функцию ExploreLine и видим, что уже в ней мы обращаемся к нашему словарю ключевых слов, мы для каждого слова проверяем, входит оно в него или нет. Что здесь важно? Что мы вот этот наш словарь ключевых слов передаем по ссылке в различные потоки, каждый из которых к этому словарю обращается, и не выполняем никакой синхронизации. У нас в коде нигде не используются mutex'ы. Почему так? Потому что наш словарь ключевых слов, наша переменная key_words, представляет собой констатный объект. Мы говорили, что чтобы возникла ситуация гонки, нужно чтобы был хотя бы один поток, который изменяет разделяемый объект. Но так как key_words — это констатная ссылка, то ни один поток в принципе не может этот словарь изменить. И поэтому нам нет необходимости выполнять синхронизацию доступа к этой переменной. И это очень важное свойство констатности в C++. Констатность гарантирует потокобезопасность. Констатному объекту нет необходимости осуществлять синхронизацию доступа. То есть в общем виде, если у вас есть некий объект виджет-класса widget, к которому обращаются несколько потоков, то вам нужно сначала изучить либо реализацию класса widget, либо его документацию, чтобы убедиться, является ли этот класс потокобезопасным. Если же у вас есть констатный объект класса widget, то вы можете вообще не заглядывать в его реализацию, потому что вам язык гарантирует, что ни один поток не может этот объект изменить, а значит, вам не нужно выполнять синхронизацию доступа к нему. Таким образом, мы в этом видео узнали, что констатность C++ гарантирует потокобезопасность. У этого свойства есть некоторые нюансы, но о них мы поговорим позже.