diff --git a/src/main/java/ru/lionarius/sync/MyCountDownLatch.java b/src/main/java/ru/lionarius/sync/MyCountDownLatch.java index e8bc71a..6d1a8c6 100644 --- a/src/main/java/ru/lionarius/sync/MyCountDownLatch.java +++ b/src/main/java/ru/lionarius/sync/MyCountDownLatch.java @@ -13,29 +13,33 @@ public class MyCountDownLatch { } public void countDown() { - synchronized (lock) { - if (count <= 0) + synchronized (this.lock) { + if (this.count <= 0) return; - count--; + this.count--; - if (count == 0) { - lock.notifyAll(); + if (this.count == 0) { + this.lock.notifyAll(); } } } public void await() throws InterruptedException { - synchronized (lock) { - while (count > 0) { - lock.wait(); + synchronized (this.lock) { + while (this.count > 0) { + this.lock.wait(); } } } + + public boolean tryAwait() { + return this.getCount() <= 0; + } public int getCount() { - synchronized (lock) { - return count; + synchronized (this.lock) { + return this.count; } } } diff --git a/src/main/java/ru/lionarius/sync/MyReentrantLock.java b/src/main/java/ru/lionarius/sync/MyReentrantLock.java index 513cd47..2b9f2be 100644 --- a/src/main/java/ru/lionarius/sync/MyReentrantLock.java +++ b/src/main/java/ru/lionarius/sync/MyReentrantLock.java @@ -8,48 +8,49 @@ public class MyReentrantLock { private Thread owner; public void lock() throws InterruptedException { - synchronized (lock) { + synchronized (this.lock) { Thread current = Thread.currentThread(); - while (isLocked() && current != owner) { - lock.wait(); + while (isLocked() && current != this.owner) { + this.lock.wait(); } - - counter++; - owner = current; + + this.counter++; + this.owner = current; } } public boolean tryLock() { - synchronized (lock) { + synchronized (this.lock) { Thread current = Thread.currentThread(); - if (isLocked() && current != owner) { + if (isLocked() && current != this.owner) { return false; } + + this.counter++; + this.owner = current; - counter++; - owner = current; return true; } } public void unlock() { - synchronized (lock) { - if (Thread.currentThread() != owner) { + synchronized (this.lock) { + if (Thread.currentThread() != this.owner) { throw new IllegalMonitorStateException("Not owner"); } + + this.counter--; - counter--; - - if (counter == 0) { - owner = null; - lock.notify(); + if (this.counter == 0) { + this.owner = null; + this.lock.notify(); } } } private boolean isLocked() { - return counter > 0; + return this.counter > 0; } } diff --git a/src/main/java/ru/lionarius/sync/MySemaphore.java b/src/main/java/ru/lionarius/sync/MySemaphore.java index 1eac0ed..83eae42 100644 --- a/src/main/java/ru/lionarius/sync/MySemaphore.java +++ b/src/main/java/ru/lionarius/sync/MySemaphore.java @@ -10,36 +10,37 @@ public class MySemaphore { } public void acquire() throws InterruptedException { - synchronized (lock) { - while (permits <= 0) { - lock.wait(); + synchronized (this.lock) { + while (this.permits <= 0) { + this.lock.wait(); } - permits--; + this.permits--; } } public boolean tryAcquire() { - synchronized (lock) { - if (permits <= 0) { + synchronized (this.lock) { + if (this.permits <= 0) { return false; } - permits--; + this.permits--; + return true; } } public void release() { - synchronized (lock) { - permits++; - lock.notify(); + synchronized (this.lock) { + this.permits++; + this.lock.notify(); } } public int availablePermits() { - synchronized (lock) { - return permits; + synchronized (this.lock) { + return this.permits; } } } diff --git a/src/test/java/MyCountDownLatchTest.java b/src/test/java/MyCountDownLatchTest.java index 6694999..279f54d 100644 --- a/src/test/java/MyCountDownLatchTest.java +++ b/src/test/java/MyCountDownLatchTest.java @@ -1,3 +1,4 @@ +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import ru.lionarius.sync.MyCountDownLatch; @@ -30,7 +31,7 @@ class MyCountDownLatchTest { assertEquals(0, latch.getCount()); } - @Test + @RepeatedTest(20) void testAwait() throws InterruptedException { var latch = new MyCountDownLatch(2); var threadFinished = new AtomicBoolean(false); @@ -39,8 +40,7 @@ class MyCountDownLatchTest { try { latch.await(); threadFinished.set(true); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException ignored) { } }); @@ -58,6 +58,7 @@ class MyCountDownLatchTest { } @Test + @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) void testMultipleThreads() throws InterruptedException { final int THREAD_COUNT = 5; var startLatch = new MyCountDownLatch(1); @@ -76,8 +77,7 @@ class MyCountDownLatchTest { Thread.sleep(100); threadsFinished[index].set(true); endLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException ignored) { } }).start(); } @@ -106,7 +106,6 @@ class MyCountDownLatchTest { void testZeroCount() throws InterruptedException { var latch = new MyCountDownLatch(0); assertEquals(0, latch.getCount()); - latch.await(); - assertTrue(true); + assertTrue(latch.tryAwait()); } } diff --git a/src/test/java/MyReentrantLockTest.java b/src/test/java/MyReentrantLockTest.java index d0356d8..16eecee 100644 --- a/src/test/java/MyReentrantLockTest.java +++ b/src/test/java/MyReentrantLockTest.java @@ -25,6 +25,11 @@ class MyReentrantLockTest { lock.unlock(); } + @Test + void testUnlock() { + assertThrows(IllegalMonitorStateException.class, lock::unlock); + } + @Test @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) void testTryLock() throws InterruptedException { @@ -68,11 +73,11 @@ class MyReentrantLockTest { threads[i] = new Thread(() -> { try { lock.lock(); - Thread.sleep(10); - lock.unlock(); threadsCompleted[index].set(true); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException ignored) { + } + finally { + lock.unlock(); } }); threads[i].start(); diff --git a/src/test/java/MySemaphoreTest.java b/src/test/java/MySemaphoreTest.java index 0eb4efe..dbc0c34 100644 --- a/src/test/java/MySemaphoreTest.java +++ b/src/test/java/MySemaphoreTest.java @@ -46,9 +46,12 @@ class MySemaphoreTest { void testMultipleThreads() throws InterruptedException { final int THREAD_COUNT = 10; final int PERMITS = 3; + var semaphore = new MySemaphore(PERMITS); + var startLatch = new CountDownLatch(1); var finishLatch = new CountDownLatch(THREAD_COUNT); + var concurrentThreads = new AtomicInteger(0); var maxConcurrentThreads = new AtomicInteger(0); @@ -57,14 +60,17 @@ class MySemaphoreTest { try { startLatch.await(); semaphore.acquire(); + int current = concurrentThreads.incrementAndGet(); maxConcurrentThreads.updateAndGet(max -> Math.max(max, current)); - Thread.sleep(100); // Имитация работы + + Thread.sleep(100); + concurrentThreads.decrementAndGet(); + semaphore.release(); finishLatch.countDown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException ignored) { } }).start(); } @@ -80,22 +86,29 @@ class MySemaphoreTest { var semaphore = new MySemaphore(1); semaphore.acquire(); assertEquals(0, semaphore.availablePermits()); - + + var startLatch = new CountDownLatch(1); + var doneLatch = new CountDownLatch(1); var thread = new Thread(() -> { try { + startLatch.countDown(); + semaphore.acquire(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + } catch (InterruptedException ignored) { } + + doneLatch.countDown(); }); thread.start(); - Thread.sleep(100); // Даем время потоку начать ожидание + startLatch.await(); + assertTrue(thread.isAlive()); assertEquals(0, semaphore.availablePermits()); semaphore.release(); - thread.join(1000); + doneLatch.await(); + assertFalse(thread.isAlive()); assertEquals(0, semaphore.availablePermits()); }