Семафор (информатика)

Поделись знанием:
Перейти к: навигация, поиск

Семафо́р (англ. semaphore) — объект, ограничивающий количество потоков, которые могут войти в заданный участок кода. Определение введено Эдсгером Дейкстрой. Семафоры используются для синхронизации и защиты передачи данных через разделяемую память, а также для синхронизации работы процессов и потоков.





Определение семафора

Семафор — это объект, над которым можно выполнить три операции.

Инициализация семафора (задать начальное значение счётчика):

init(n):
    счётчик := n

Захват семафора (ждать пока счётчик станет больше 0, после этого уменьшить счётчик на единицу):

enter():
    счётчик := счётчик - 1

Освобождение семафора (увеличить счётчик на единицу):

leave():
    счётчик := счётчик + 1

Предположим, что есть такой участок кода:

semaphore.init(5);
// .....
// .....
void DoSomething()
{
    semaphore.enter();
    // .......
    semaphore.leave();
}

Тогда не более пяти потоков могут одновременно выполнять функцию DoSomething().

В более сложных семафорах может использоваться очередь; при этом потоки, ожидающие освобождения семафора, будут проходить через семафор именно в том порядке, в котором они вызывали enter().

Применение семафоров

Некоторые из проблем, которые могут решать семафоры:

  • запрет одновременного выполнения заданных участков кода (критические секции);
  • поочерёдный доступ к критическому ресурсу (важному ресурсу, для которого невозможен (или нежелателен) одновременный доступ);
  • синхронизация процессов и потоков (например, можно инициировать обработку события отпусканием семафора).

Следующий пример показывает, как наладить поочерёдный доступ к консоли.

semaphore.init(1);

// Поток 1:
semaphore.enter();
cout << "Состояние массива: ";
for (int i=0; i<n; i++)
    cout << a[i] << ' ';
cout << '\n';
semaphore.leave();

// Поток 2:
semaphore.enter();
cout << "Нажато Esc.\n";
semaphore.leave();

Этот код поможет предотвратить появление вывода наподобие

Состояние массива: 1 2 3 Нажато Esc.
4 5 6

Проблемы семафоров

Во-первых, можно написать программу с «утечкой семафора», вызвав enter() и забыв вызвать leave(). Реже встречаются ошибки, когда дважды вызывается leave().

Во-вторых, семафоры чреваты взаимной блокировкой потоков. В частности, опасен такой код:

// Поток 1:
semaphore1.enter();
semaphore2.enter();
// ...
semaphore2.leave();
semaphore1.leave();

// Поток 2:
semaphore2.enter();
semaphore1.enter();
// ...
semaphore1.leave();
semaphore2.leave();

См. также

Напишите отзыв о статье "Семафор (информатика)"

Литература

  • Грегори Р. Эндрюс. Основы многопоточного, параллельного и распределённого программирования. — Вильямс, 2003.

Ссылки

  • [www.maqdev.com/post.aspx?id=40ef9205-c67c-4797-b80b-ce77ebfa7dde Пример реализации семафора с политикой FIFO в Microsoft.NET]

Отрывок, характеризующий Семафор (информатика)

– Он верно вам говорил про свою детскую любовь к Наташе?
– А была детская любовь? – вдруг неожиданно покраснев, спросил князь Андрей.
– Да. Vous savez entre cousin et cousine cette intimite mene quelquefois a l'amour: le cousinage est un dangereux voisinage, N'est ce pas? [Знаете, между двоюродным братом и сестрой эта близость приводит иногда к любви. Такое родство – опасное соседство. Не правда ли?]
– О, без сомнения, – сказал князь Андрей, и вдруг, неестественно оживившись, он стал шутить с Пьером о том, как он должен быть осторожным в своем обращении с своими 50 ти летними московскими кузинами, и в середине шутливого разговора встал и, взяв под руку Пьера, отвел его в сторону.
– Ну что? – сказал Пьер, с удивлением смотревший на странное оживление своего друга и заметивший взгляд, который он вставая бросил на Наташу.
– Мне надо, мне надо поговорить с тобой, – сказал князь Андрей. – Ты знаешь наши женские перчатки (он говорил о тех масонских перчатках, которые давались вновь избранному брату для вручения любимой женщине). – Я… Но нет, я после поговорю с тобой… – И с странным блеском в глазах и беспокойством в движениях князь Андрей подошел к Наташе и сел подле нее. Пьер видел, как князь Андрей что то спросил у нее, и она вспыхнув отвечала ему.
Но в это время Берг подошел к Пьеру, настоятельно упрашивая его принять участие в споре между генералом и полковником об испанских делах.
Берг был доволен и счастлив. Улыбка радости не сходила с его лица. Вечер был очень хорош и совершенно такой, как и другие вечера, которые он видел. Всё было похоже. И дамские, тонкие разговоры, и карты, и за картами генерал, возвышающий голос, и самовар, и печенье; но одного еще недоставало, того, что он всегда видел на вечерах, которым он желал подражать.
Недоставало громкого разговора между мужчинами и спора о чем нибудь важном и умном. Генерал начал этот разговор и к нему то Берг привлек Пьера.


На другой день князь Андрей поехал к Ростовым обедать, так как его звал граф Илья Андреич, и провел у них целый день.
Все в доме чувствовали для кого ездил князь Андрей, и он, не скрывая, целый день старался быть с Наташей. Не только в душе Наташи испуганной, но счастливой и восторженной, но во всем доме чувствовался страх перед чем то важным, имеющим совершиться. Графиня печальными и серьезно строгими глазами смотрела на князя Андрея, когда он говорил с Наташей, и робко и притворно начинала какой нибудь ничтожный разговор, как скоро он оглядывался на нее. Соня боялась уйти от Наташи и боялась быть помехой, когда она была с ними. Наташа бледнела от страха ожидания, когда она на минуты оставалась с ним с глазу на глаз. Князь Андрей поражал ее своей робостью. Она чувствовала, что ему нужно было сказать ей что то, но что он не мог на это решиться.