1
0
This commit is contained in:
2024-11-14 13:36:37 +03:00
parent 5bae7a279b
commit 6a61a96a16
6 changed files with 82 additions and 59 deletions

View File

@@ -13,29 +13,33 @@ public class MyCountDownLatch {
} }
public void countDown() { public void countDown() {
synchronized (lock) { synchronized (this.lock) {
if (count <= 0) if (this.count <= 0)
return; return;
count--; this.count--;
if (count == 0) { if (this.count == 0) {
lock.notifyAll(); this.lock.notifyAll();
} }
} }
} }
public void await() throws InterruptedException { public void await() throws InterruptedException {
synchronized (lock) { synchronized (this.lock) {
while (count > 0) { while (this.count > 0) {
lock.wait(); this.lock.wait();
} }
} }
} }
public boolean tryAwait() {
return this.getCount() <= 0;
}
public int getCount() { public int getCount() {
synchronized (lock) { synchronized (this.lock) {
return count; return this.count;
} }
} }
} }

View File

@@ -8,48 +8,49 @@ public class MyReentrantLock {
private Thread owner; private Thread owner;
public void lock() throws InterruptedException { public void lock() throws InterruptedException {
synchronized (lock) { synchronized (this.lock) {
Thread current = Thread.currentThread(); Thread current = Thread.currentThread();
while (isLocked() && current != owner) { while (isLocked() && current != this.owner) {
lock.wait(); this.lock.wait();
} }
counter++; this.counter++;
owner = current; this.owner = current;
} }
} }
public boolean tryLock() { public boolean tryLock() {
synchronized (lock) { synchronized (this.lock) {
Thread current = Thread.currentThread(); Thread current = Thread.currentThread();
if (isLocked() && current != owner) { if (isLocked() && current != this.owner) {
return false; return false;
} }
counter++; this.counter++;
owner = current; this.owner = current;
return true; return true;
} }
} }
public void unlock() { public void unlock() {
synchronized (lock) { synchronized (this.lock) {
if (Thread.currentThread() != owner) { if (Thread.currentThread() != this.owner) {
throw new IllegalMonitorStateException("Not owner"); throw new IllegalMonitorStateException("Not owner");
} }
counter--; this.counter--;
if (counter == 0) { if (this.counter == 0) {
owner = null; this.owner = null;
lock.notify(); this.lock.notify();
} }
} }
} }
private boolean isLocked() { private boolean isLocked() {
return counter > 0; return this.counter > 0;
} }
} }

View File

@@ -10,36 +10,37 @@ public class MySemaphore {
} }
public void acquire() throws InterruptedException { public void acquire() throws InterruptedException {
synchronized (lock) { synchronized (this.lock) {
while (permits <= 0) { while (this.permits <= 0) {
lock.wait(); this.lock.wait();
} }
permits--; this.permits--;
} }
} }
public boolean tryAcquire() { public boolean tryAcquire() {
synchronized (lock) { synchronized (this.lock) {
if (permits <= 0) { if (this.permits <= 0) {
return false; return false;
} }
permits--; this.permits--;
return true; return true;
} }
} }
public void release() { public void release() {
synchronized (lock) { synchronized (this.lock) {
permits++; this.permits++;
lock.notify(); this.lock.notify();
} }
} }
public int availablePermits() { public int availablePermits() {
synchronized (lock) { synchronized (this.lock) {
return permits; return this.permits;
} }
} }
} }

View File

@@ -1,3 +1,4 @@
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;
import ru.lionarius.sync.MyCountDownLatch; import ru.lionarius.sync.MyCountDownLatch;
@@ -30,7 +31,7 @@ class MyCountDownLatchTest {
assertEquals(0, latch.getCount()); assertEquals(0, latch.getCount());
} }
@Test @RepeatedTest(20)
void testAwait() throws InterruptedException { void testAwait() throws InterruptedException {
var latch = new MyCountDownLatch(2); var latch = new MyCountDownLatch(2);
var threadFinished = new AtomicBoolean(false); var threadFinished = new AtomicBoolean(false);
@@ -39,8 +40,7 @@ class MyCountDownLatchTest {
try { try {
latch.await(); latch.await();
threadFinished.set(true); threadFinished.set(true);
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
} }
}); });
@@ -58,6 +58,7 @@ class MyCountDownLatchTest {
} }
@Test @Test
@Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
void testMultipleThreads() throws InterruptedException { void testMultipleThreads() throws InterruptedException {
final int THREAD_COUNT = 5; final int THREAD_COUNT = 5;
var startLatch = new MyCountDownLatch(1); var startLatch = new MyCountDownLatch(1);
@@ -76,8 +77,7 @@ class MyCountDownLatchTest {
Thread.sleep(100); Thread.sleep(100);
threadsFinished[index].set(true); threadsFinished[index].set(true);
endLatch.countDown(); endLatch.countDown();
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
} }
}).start(); }).start();
} }
@@ -106,7 +106,6 @@ class MyCountDownLatchTest {
void testZeroCount() throws InterruptedException { void testZeroCount() throws InterruptedException {
var latch = new MyCountDownLatch(0); var latch = new MyCountDownLatch(0);
assertEquals(0, latch.getCount()); assertEquals(0, latch.getCount());
latch.await(); assertTrue(latch.tryAwait());
assertTrue(true);
} }
} }

View File

@@ -25,6 +25,11 @@ class MyReentrantLockTest {
lock.unlock(); lock.unlock();
} }
@Test
void testUnlock() {
assertThrows(IllegalMonitorStateException.class, lock::unlock);
}
@Test @Test
@Timeout(value = 1000, unit = TimeUnit.MILLISECONDS) @Timeout(value = 1000, unit = TimeUnit.MILLISECONDS)
void testTryLock() throws InterruptedException { void testTryLock() throws InterruptedException {
@@ -68,11 +73,11 @@ class MyReentrantLockTest {
threads[i] = new Thread(() -> { threads[i] = new Thread(() -> {
try { try {
lock.lock(); lock.lock();
Thread.sleep(10);
lock.unlock();
threadsCompleted[index].set(true); threadsCompleted[index].set(true);
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt(); }
finally {
lock.unlock();
} }
}); });
threads[i].start(); threads[i].start();

View File

@@ -46,9 +46,12 @@ class MySemaphoreTest {
void testMultipleThreads() throws InterruptedException { void testMultipleThreads() throws InterruptedException {
final int THREAD_COUNT = 10; final int THREAD_COUNT = 10;
final int PERMITS = 3; final int PERMITS = 3;
var semaphore = new MySemaphore(PERMITS); var semaphore = new MySemaphore(PERMITS);
var startLatch = new CountDownLatch(1); var startLatch = new CountDownLatch(1);
var finishLatch = new CountDownLatch(THREAD_COUNT); var finishLatch = new CountDownLatch(THREAD_COUNT);
var concurrentThreads = new AtomicInteger(0); var concurrentThreads = new AtomicInteger(0);
var maxConcurrentThreads = new AtomicInteger(0); var maxConcurrentThreads = new AtomicInteger(0);
@@ -57,14 +60,17 @@ class MySemaphoreTest {
try { try {
startLatch.await(); startLatch.await();
semaphore.acquire(); semaphore.acquire();
int current = concurrentThreads.incrementAndGet(); int current = concurrentThreads.incrementAndGet();
maxConcurrentThreads.updateAndGet(max -> Math.max(max, current)); maxConcurrentThreads.updateAndGet(max -> Math.max(max, current));
Thread.sleep(100); // Имитация работы
Thread.sleep(100);
concurrentThreads.decrementAndGet(); concurrentThreads.decrementAndGet();
semaphore.release(); semaphore.release();
finishLatch.countDown(); finishLatch.countDown();
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
} }
}).start(); }).start();
} }
@@ -81,21 +87,28 @@ class MySemaphoreTest {
semaphore.acquire(); semaphore.acquire();
assertEquals(0, semaphore.availablePermits()); assertEquals(0, semaphore.availablePermits());
var startLatch = new CountDownLatch(1);
var doneLatch = new CountDownLatch(1);
var thread = new Thread(() -> { var thread = new Thread(() -> {
try { try {
startLatch.countDown();
semaphore.acquire(); semaphore.acquire();
} catch (InterruptedException e) { } catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
} }
doneLatch.countDown();
}); });
thread.start(); thread.start();
Thread.sleep(100); // Даем время потоку начать ожидание startLatch.await();
assertTrue(thread.isAlive()); assertTrue(thread.isAlive());
assertEquals(0, semaphore.availablePermits()); assertEquals(0, semaphore.availablePermits());
semaphore.release(); semaphore.release();
thread.join(1000); doneLatch.await();
assertFalse(thread.isAlive()); assertFalse(thread.isAlive());
assertEquals(0, semaphore.availablePermits()); assertEquals(0, semaphore.availablePermits());
} }