Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Однократно вызываемые функции
Остается разобраться с одним вопросом: как сделать функции инициализации (такие как конструкторы) потокобезопасными. Например, когда «глобальный» экземпляр объекта создается как синглетон уровня приложения (единственный существующий в приложении объект данного типа), существует проблема порядка инстанцирования, поэтому используется функция, возвращающая статический экземпляр, которая гарантирует, что при первом к ней обращении этот экземпляр будет создан. Проблема в том, что если несколько потоков одновременно вызовут эту функцию, конструктор для статического объекта также может быть вызван несколько раз, и результаты могут оказаться плачевными. Решение проблемы в так называемых «однократно вызываемых функциях» (once routine). Такая функция вызывается в приложении только один раз. Если несколько потоков попытаются ее вызвать одновременно, только один из них получит такую возможность, а в это время все остальные потоки будут ждать, пока выполнение функции не завершится. Чтобы гаранти ровать однократное выполнение, такая функция вызывается косвенно через другую функцию, которой передается указатель на исходную и ссылка на специальный флаг, сигнализирующий о факте вызова функции. Этот флаг инициализируется статически, что гарантирует инициализацию в период компиляции, а не в период выполнения. И таким образом не представляет проблемы для многопоточной инициализации. Библиотека Boost.Threads предоставляет возможность однократного вызова функции посредством boost::call_once, а также определяет тип для флага boost::once_flag и специальную макроподстановку, используемую для статической инициализации флага, BOOST_ONCE_INIT. Пример 6 показывает очень простой пример использования boost::call_once. Глобальное целое статически инициализируется нулем, а экземпляр boost::once_flag статически инициализируется с помощью BOOST_ONCE_INIT. Основной поток запускает два потока, каждый из которых пытается «инициализировать» глобальное целое, вызывая boost::call_once с указателем на функцию, инкрементирующую целое. Затем основной поток дожидается завершения обоих потоков и выводит конечное значение целого в std::cout. Вывод демонстрирует, что функция действительно была вызвана только однажды, так как значение целого – единица.
// Пример 6 #include <boost/thread/thread.hpp> #include <boost/thread/once.hpp> #include <iostream> int i = 0; boost::once_flag flag = BOOST_ONCE_INIT; void init() { ++i; } void thread() { boost::call_once(&init, flag); } int main(int argc, char* argv[]) { boost::thread thrd1(&thread); boost::thread thrd2(&thread); thrd1.join(); thrd2.join(); std::cout << i << std::endl; return 0; }
Инициализация параметров Есть ещё классная штука - возможность инициализировать параметры, запустив функцию однократно. Например, есть три потока, которые обращаются к переменной х, но сперва её надо инициализировать, причём только один раз, а не всеми тремя потоками сразу. Для этого предусмотрен специальный механизм: int i; boost::once_flag flag = BOOST_ONCE_FLAG; void init() { i = 0; } void thread() { boost::call_once(&init, flag); // дальнейший код } Так вот, инициализация произойдёт всего один раз, независимо от числа конкурирующих потоков. Ожидание внутри потоков Иногда надо подождать немного в потоке. Для этого есть два разных способа · boost::this_thread::sleep(params) · boost::this_thread::yield() Первый (с установленными параметрами) замораживает поток на указанное время. Второй действует хитрее - он ненадолго замораживает поток, отдавая тем самым ресурсы другим участникам состязания за них. Эдакая джентльменская уступка.
|
|||||
Последнее изменение этой страницы: 2016-12-11; просмотров: 236; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.188.20.56 (0.007 с.) |