@artemfisher

Почему в semaphore методы acquaire() и tryAcquire() захватывают блокировку по разному?

Добрый день.
Не могу понять почему при использовании tryAcquire() не отрабатывает метод Thread.sleep(),
при вызове acquire() отрабатывает нормально. В документации не нашел объяснения.

public class TestApp {

	public static void main(String[] args)
	{
		Semaphore sem = new Semaphore(2);
		
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();
		new Thread(new Hello(sem)).start();				
	}		
}

class Hello implements Runnable
{
	private Semaphore semaphore;
	
	Hello(Semaphore semaphore)
	{
		this.semaphore = semaphore;
	}
	
	public void run()
	{		
		try
		{
			if(!semaphore.tryAcquire())
				System.out.println(Thread.currentThread().getName()+"-do not allowed");
			
			System.out.println(Thread.currentThread().getName());
			Thread.sleep(1000);
		}
		catch(InterruptedException ex) 
		{
			Thread.currentThread().interrupt();
		}
		finally
		{
			System.out.println(Thread.currentThread().getName()+"-released");
			semaphore.release();
		}
	}	
}


В консоль выводит следующее:
Thread-0
Thread-1
Thread-4-do not allowed
Thread-6-do not allowed
Thread-3-do not allowed
Thread-5-do not allowed
Thread-5
Thread-2-do not allowed
Thread-3
Thread-6
Thread-4
Thread-2
Thread-0-released
Thread-1-released
Thread-5-released
Thread-6-released
Thread-3-released
Thread-4-released
Thread-2-released

Т.е. метод release() еще не высвободил ресурс для захвата, но другие потоки его захватывают, несмотря на это.

Если же внутри try я меняю tryAcquire() на acquire() все работает нормально.

try
{
	semaphore.acquire();		
	System.out.println(Thread.currentThread().getName());
	Thread.sleep(1000);
}


Вывод в консоль:
Thread-0
Thread-2
Thread-2-released
Thread-0-released
Thread-3
Thread-5
Thread-5-released
Thread-3-released
Thread-4
Thread-1
Thread-4-released
Thread-6
Thread-1-released
Thread-6-released
  • Вопрос задан
  • 72 просмотра
Пригласить эксперта
Ответы на вопрос 1
AshBlade
@AshBlade
Просто хочу быть счастливым
А что тут не понятно?
1. Все потоки быстро запустились, вызвали tryAcquire и, т.к. он не блокирующий, тут же вызывается Thread.Sleep() на всех потоках - поэтому в первом случае в конце видны Thread-x-released (все потоки закончили работу). Время выполнения всего приложения -
2. Все потоки постепенно захватывают семафор, т.е. ждут пока предыдущий его освободит и только потом засыпают. Уже тут время выполнения - 1с * (кол-во потоков / 2)

P.S. Не забывай вызывать Thread.join после запуска!
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы