앞서 synchronized 블럭 동기화를 알아볼때 lock패키지에 대한 언급을 했었다.
https://standout.tistory.com/1428
lock클래스의 종류는 3가지가 있다.
ReentrantLock
ReentrantReadWriteLock
StampedLock
ReentrantLock
`ReentrantLock`을 사용하여 공유 자원에 대한 접근을 동기화한다.
`increment()` 메서드에서 락을 획득하고 해제한다.
예시는 두 개의 스레드가 카운터를 증가시키는 작업을 동시에 수행하고, 최종 카운터 값이 올바르게 출력되는지 확인한다.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
public int getCount() {
return count;
}
}
public class ReentrantLockExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Counter value: " + counter.getCount());
}
}
출력결과: Counter value: 2000
ReentrantReadWriteLock
`ReentrantReadWriteLock`을 사용하여 공유 자원에 대한 읽기와 쓰기를 분리하여 동기화한다.
예시는 작성자가 데이터를 쓰고, 독자가 데이터를 읽는 상황을 시뮬레이션한다.
import java.util.concurrent.locks.ReentrantReadWriteLock;
class SharedResource {
private int data = 0;
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void writeData(int newData) {
lock.writeLock().lock();
try {
data = newData;
} finally {
lock.writeLock().unlock();
}
}
public int readData() {
lock.readLock().lock();
try {
return data;
} finally {
lock.readLock().unlock();
}
}
}
public class ReentrantReadWriteLockExample {
public static void main(String[] args) {
SharedResource sharedResource = new SharedResource();
Thread writerThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
sharedResource.writeData(i);
System.out.println("Writer wrote: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread readerThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
int data = sharedResource.readData();
System.out.println("Reader read: " + data);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
writerThread.start();
readerThread.start();
}
}
출력결과:
Writer wrote: 0
Writer wrote: 1
Reader read: 1
Reader read: 1
Writer wrote: 2
Reader read: 2
Reader read: 2
Writer wrote: 3
Reader read: 3
Reader read: 3
Writer wrote: 4
Reader read: 4
Reader read: 4
StampedLock
`StampedLock`을 사용하여 공유 자원에 대한 읽기 작업과 쓰기 작업을 분리하여 동기화한다.
예시는 한 스레드가 위치를 이동시키고,
다른 스레드가 현재 위치에서 원점까지의 거리를 계산하는 상황을 시뮬레이션한다.
import java.util.concurrent.locks.StampedLock;
class Point {
private double x, y;
private final StampedLock lock = new StampedLock();
void move(double deltaX, double deltaY) {
long stamp = lock.writeLock();
try {
x += deltaX;
y += deltaY;
} finally {
lock.unlockWrite(stamp);
}
}
double distanceFromOrigin() {
long stamp = lock.tryOptimisticRead();
double currentX = x, currentY = y;
if (!lock.validate(stamp)) {
stamp = lock.readLock();
try {
currentX = x;
currentY = y;
} finally {
lock.unlockRead(stamp);
}
}
return Math.sqrt(currentX * currentX + currentY * currentY);
}
}
public class StampedLockExample {
public static void main(String[] args) {
Point point = new Point();
Thread writerThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
point.move(i, i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread readerThread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
double distance = point.distanceFromOrigin();
System.out.println("Distance from origin: " + distance);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
writerThread.start();
readerThread.start();
}
}
출력결과:
Distance from origin: 0.0
Distance from origin: 1.4142135623730951
Distance from origin: 2.8284271247461903
Distance from origin: 4.242640687119285
Distance from origin: 5.656854249492381
'JAVA' 카테고리의 다른 글
하나의 작업을 작은 단위로 나눠서 여러 스레드가 동시에 처리한다, fork & join 프레임웍 (0) | 2024.02.26 |
---|---|
volatile, 공유 변수의 가시성을 보장하다 (0) | 2024.02.26 |
synchronized 동기화를 보완하다, wait()과 notify() 락을 가진 상태로 오랜시간 유지하지않도록 (0) | 2024.02.26 |
synchronized 를 이용한 스레드의 동기화 (0) | 2024.02.26 |
스레드의 스케줄링/실행제어, 스레드의 상태를 지정하다. (0) | 2024.02.26 |