Критическая секция гарантирует вам, что куски кода программы, огороженные ей, не будут выполняться одновременно. Строго говоря, критическая секция не является объектом ядра. Она представляет собой структуру, содержащую несколько флагов и какой-то (не важно) объект ядра. При входе в критическую секцию сначала проверяются флаги, и если выясняется, что она уже занята другим потоком, то выполняется обычная wait-функция. Критическая секция примечательна тем, что для проверки, занята она или нет, программа не переходит в режим ядра (не выполняется wait-функция) а лишь проверяются флаги. Из-за этого считается, что синхронизация с помощью критических секций наиболее быстрая. Такую синхронизацию называют " синхронизация в пользовательском режиме ".
Пример 9. Снова рассмотрим очередь элементов. Один из вариантов ее реализации - двусвязный список. С точки зрения многопоточности, опасными являются операции добавления и удаления элементов из очереди. Существует вероятность, что несколько потоков одновременно начнут перестраивать указатели и связность очереди нарушится. Чтобы этого избежать, используем критическую секцию.
typedef... ItemData; // Элемент очереди: данные и два указателя на предыдущий и следующий элементы typedef struct _ItemStruct { ItemData data; struct _ItemStruct * prev,*next; } Item; // Описание класса "Очередь" class CMyQueue { CRITICAL_SECTION m_crisec; // Критическая секция Item * m_Begin; // Указатель на первый элемент Item * m_End; // Указатель на последний элемент int m_Count; // Количество элементов public: CMyQueue() { // Инициализируем критическую секцию InitializeCriticalSection(&m_crisec); // Инициализируем переменные m_Count = 0; m_Begin = m_End = NULL; } ~CMyQueue() { // Удаляем все элементы очереди while(m_Count) GetItem(); // Удаляем критическую секцию DeleteCriticalSection(&m_crisec); } void AddItem(ItemData data) { Item * NewItem; Item * OldFirstItem; NewItem = new Item(); // New item NewItem->next = NULL; NewItem->prev = NULL; NewItem->data = data; // ------------------------ Этот кусок не может выполняться параллельно EnterCriticalSection(&m_crisec); // Заходим в к.с. (ждем входа) OldFirstItem = m_Begin; m_Begin = NewItem; NewItem->next = OldFirstItem; if (OldFirstItem) OldFirstItem->prev = NewItem; else m_End = NewItem; m_Count++; LeaveCriticalSection(&m_crisec); // Выходим из к.с. // ------------------------ Этот кусок не может выполняться параллельно } ItemData GetItem() { ItemData data; // ------------------------ Этот кусок не может выполняться параллельно EnterCriticalSection(&m_crisec); // Заходим в к.с. (ждем входа) if (!m_End) data = NULL; else { data = m_End->data; if (m_End->prev) { m_End->prev ->next = NULL; m_End = m_End->prev; } else { m_End = NULL; m_Begin = NULL; } m_Count --; } LeaveCriticalSection(&m_crisec); // Выходим из к.с. // ------------------------ Этот кусок не может выполняться параллельно return data; }; };
Написать программу, которая создаёт несколько потоков и синхронизирует их работу с использованием инструментов Critical Section, mutex и semaphore. Для управления работой потоков использовать только функции синхронизации.
Поток считает сумму ряда по 100 элементов, после чего он переходит в режим ожидания, пока в основном потоке пользователь не нажмет любую клавишу. На экран выводить текущее значение суммы ряда. Использовать mutex.
Создать 2 потока, которые по очереди считают значение определенного интеграла на заданном интервале, причем каждый поток считает только значение только на своём интервале. Оба потока используют одни и те же глобальные переменные для расчётов. Текущее значение интеграла и номер активного потока выводиться на экран. Использовать Critical section.
Создать 2 потока. Первый поток уменьшает значение какой либо глобальной переменной на фиксированное значение, второй – увеличивает то же значение. При нажатии на клавиши поток блокируется/активизируется. Значение величины и состояние каждого потока выводится на экран. Использовать mutex.
Создать 4 потока, которые увеличивают значение целой глобальной переменной. При достижении определенного значения переменная обнуляется. Пользователь с клавиатуры задаёт число одновременно работающих потоков. Текущее значение переменной выводится на экран. Использовать semaphore.
Создать 3 потока, которые через случайное время (50 – 1500 мс) меняют значение глобальной переменной на случайную величину (-10 … 10). После чего блокируют изменение этой переменной на это же время. Использовать функцию sleep и critical section. Отображать на экране значение этой переменной, и номер потока, изменивший её значение в последний раз.
Создать 4 потока, которые через равные интервалы времени (1 сек) меняют в строке местами 2 произвольных символа. Пользователь с клавиатуры задаёт количество одновременно работающих потоков. На экране отображать текущее состояние строки.
Создать 3 потока, которые по очереди рассчитывают значения функции на заданном диапазоне с заданным шагом. Каждый поток рассчитывает только по одному значению. На экран выводить текущее значение аргумента и функции, номер потока, рассчитавшего последнее значение. Использовать mutex.
Создать 2 потока. При нажатии на клавиши клавиатуры активизируется первый поток на какое-то случайное время (300-2000 мс). Каждые 200 мс он разрешает/запрещает расчет суммы числового ряда, которая считается вторым потоком. На экран выводить текущее значение суммы ряда. Использовать mutex.
Создать 2 потока. Первый через произвольное время (200-1000 мс) удаляет из начала строки символ (если строка не пуста) и блокирует изменение строки на 200 мс. Второй поток – добавляет символ в конец строки через 300-1200 мс, и блокирует изменение строки на 300мс. На экране отображать текущую строку, и номер потока, последним менявший строку. Использовать critical section.
Создать 2 потока, которые меняют значения 2х элементов массива в произвольной позиции по следующим правилам. Первый поток к значению большего элемента прибавляет 1, а от значения меньшего – отнимает 1. Второй поток – к меньшему прибавляет 1, от большего элемента – отнимает 1. Пользователь при нажатии клавиши моет блокировать/разрешать работу каждого потока. На экран выводить текущие значения элементов массива.
Создать 2 потока. Первый поток удаляет первый символ строки каждые 500 мс. Второй поток добавляет символ в конец строки через случайные промежутки времени (100 – 1000 мс). При нажатии на клавиши блокируется/разрешается работа каждого потока в отдельности. Для управления работой потоков использовать critical section.
Создать 3 потока. Первый поток добавляет символ «1» в конец строки через 250 – 2000 мс. Второй поток добавляет символ «2» в начало строки через 250 – 2000 мс. Третий поток удаляет символ из середины строки через каждые 250 мс. Пользователь с клавиатуры задает количество одновременно работающих потоков (0-3). Использовать semaphore.
Создать 2 потока. Первый поток циклически сдвигает символы текста вправо через случайные промежутки времени (100 – 2000 мс), второй поток – сдвигает влево. После сдвига изменение текста блокируется на время 500 мс. Использовать critical section и функцию sleep.
Создать 3 потока. Каждый поток считает сумму 1000 значений функции y=sin(x) с шагом 0.0001. Для вычислений использовать глобальные переменные. Для синхронизации вычислений использовать critical section.
Создать 3 потока, каждый из которых через произвольное время (100 – 3000 мс) удаляет из начала строки символ и добавляет в конец строки свой номер. После чего блокирует строку от изменений на 250 мс. Использовать critical section
Создать 2 потока. Первый поток генерирует через 100-500 мс случайное число. Второй поток считает среднее арифметическое этих случайных чисел. Значения выводятся на экран. Использовать mutex.
Создать 3 потока. Первый поток циклически сдвигает текст влево, второй – сдвигает циклически вправо, третий – добавляет/удаляет символ в/из середины строки. Потоки выполняют свои действия через 100 – 2000 мс, после чего блокируют изменение строки на 200 мс. Если строка блокирована, то время до выполнения потоком следующей итерации удваивается. Использовать функцию sleep и critical section.
Создать 2 потока. Первый поток считает значение функции y=cos(x), начиная от 0 с шагом 0.001. Второй поток считает сумму значений этой функции. Использовать mutex.
Создать 2 потока, которые производят циклический сдвиг цифр числа через каждые 200 мс. Пользователь, нажимая цифровые на клавиши, задаёт количество итераций, выполняемых потоками. Использовать semaphore.
Создать 2 потока. Первый поток считает сумму положительных чисел, введенных пользователем с клавиатуры, второй поток – сумму отрицательных. Текущие значения выводить на экран. Использовать mutex.
lektsii.net - Лекции.Нет - 2014-2025 год. (0.075 сек.)
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав