Страницы

Поиск по вопросам

понедельник, 11 марта 2019 г.

Semaphore на примитивных функциях Java

Задача - написать семафор без util.concurrent.*, только wait/notify/notifyAll Сам семафор:
public class MySemaphore { private int permits;
public MySemaphore(int permits) { this.permits = permits; }
public synchronized void acquire() throws InterruptedException { if (permits > 0) { permits--; }
else { this.wait(); permits--; } }
public synchronized void release() { permits++;
if (permits > 0) { this.notify(); } }
public boolean tryAcquire() { if (permits > 0) { return true; }
return false; } }
Два типа потоков для проверки:
1) Инкрементный
public class IncrementThread implements Runnable {
MySemaphore semaphore; String name; int count;
public String getName() { return name; }
public IncrementThread(MySemaphore semaphore, String name, int count) {
this.semaphore = semaphore; this.name = name; this.count = count; System.out.println(name + " was created"); }
@Override public synchronized void run() { System.out.println(Thread.currentThread().getName() + " is waiting for permit");
try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " is got for permit"); for (int i=0; i2) Дикрементный
public class DecrementThread implements Runnable { MySemaphore semaphore; String name; int count;
public DecrementThread(MySemaphore semaphore, String name, int count) { this.semaphore = semaphore; this.name = name; this.count = count; System.out.println(name + " was created"); }
@Override public synchronized void run() { System.out.println(Thread.currentThread().getName() + " is waiting for permit");
try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + " is got for permit"); for (int i=0; iОтдельный класс, который собираюсь мучить из разных потоков:
public class SharedValue { static volatile int count = 0; }
И сам тест:
public class MySemaphoreTest {
public static void main(String[] args) { MySemaphore semaphore = new MySemaphore(2); System.out.println("Semaphore with 2 permits was created"); System.out.println("Shared: " + SharedValue.count); IncrementThread thread1 = new IncrementThread(semaphore, "First increment thread", 3); IncrementThread thread2 = new IncrementThread(semaphore, "Second increment thread", 4); DecrementThread thread3 = new DecrementThread(semaphore, "First decrement thread", 7); //DecrementThread thread4 = new DecrementThread(semaphore, "Second decrement thread", 5);
new Thread(thread1, "firstIncrementThread").start(); new Thread(thread2, "secondIncrementThread").start(); new Thread(thread3, "firstDecrementThread").start(); //new Thread(thread4, "secondDecrementThread").start(); } }
Как мне кажется (по-крайней мере, так задумывалось), в конце исполнения программы я должен получить SharedValue.count = 0, а получаю какой-то рандом.
В логах видно, что нити после нескольких итераций "выстреливают" результат одновременно, хотя опять-же, по задумке, должны проводить операцию раз в секунду.
Проблема в реализации семафора или в тестировании?


Ответ

Результат одновременно "выстреливают" не потоки, а логи этих потоков. Сами потоки работают как положено с задержкой в 2 секунды.

Добавьте два synchronized метода incrementCount и decrementCount, и работайте с ними вместо переменной напрямую..
public class SharedValue { private static volatile int count = 0;
public static int getCount() { return count; }
public static synchronized void incrementCount() { count++; }
public static synchronized void decrementCount() { count--; } }

Комментариев нет:

Отправить комментарий