Разница между семафором, инициализированным с 1 и 0

пожалуйста, скажите, что такое семафор разницы, инициализированный с 1 и нулем. как показано ниже:

public static Semaphore semOne = new Semaphore(1);

и

public static Semaphore semZero = new Semaphore(0);

3 ответов


аргументом для экземпляра семафора является количество доступных "разрешений". Это может быть любое целое число, а не только 0 или 1.

на semZero все acquire() вызовы будут блокировать и tryAcquire() вызовы вернут false, пока вы не сделаете release()

на semOne первый acquire() вызовы будут успешными, а остальные будут блокироваться до первого выпуска.

класс хорошо документирован здесь.

параметры: разрешения-начальное количество доступных разрешений. Этот значение может быть отрицательным, и в этом случае релизы должны произойти до приобретение будет предоставлено.


конструктор параметр permits (начальный счетчик семафоров) - это количество вызовов Semaphore.aquire() Это можно сделать до того, как счетчик (разрешения) равен нулю, а acquire()блоки.

1 является нормальным значением, чтобы гарантировать, что только один поток проходит приобретение.

semaphore.acquire();
try {
    // Critical region
    ...
} finally {
    semaphore.release();
}

для использования 0 посмотреть здесь.

семафор - это низкоуровневый механизм параллелизма: счетчик при достижении нуля блокирование выполнения потока. Это происходит от Дейкстра где двоичный семафор (0, 1) является метафорой для железнодорожного семафора, говорящего pass (остановка, когда 0, pass --permits) и в конце защищенного пути делает выпуск (++permits).


когда я впервые прочитал документацию семафора, я также неправильно истолковал объяснение. Главное, что я пропустил, - это часть "...Начальное количество разрешений...'. Как-то я думал, что это будет количество разрешений, которые будут доступны как максимум, но это не так. В конце концов семафор просто подсчитывает от любого числа, но только запускает потоки enable waiting (которые используют acquire), когда разрешения семафора выше 1.

простая часть (не threading) код показывает это тоже:

@Test
public void testNegativeSemaphore()
{
    Semaphore semaphore = new Semaphore(-2);

    assertEquals(-2, semaphore.availablePermits());
    semaphore.release();
    assertEquals(-1, semaphore.availablePermits());
    semaphore.release();
    assertEquals(0, semaphore.availablePermits());
    semaphore.release();
    assertEquals(1, semaphore.availablePermits());
}

Как показывает код, доступные разрешения увеличиваются при каждом выпуске, только чтобы позволить другим потокам получить разрешение, как только значение достигнет 1 или выше.

обратите внимание, что оттуда availablePermits не может стать отрицательным с помощью aqcuire, потому что, если есть 0 разрешений, весь смысл семафора-ждать разрешения, чтобы стать доступным снова!