Задача - написать семафор без 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; i
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--;
}
}
Комментариев нет:
Отправить комментарий