반응형

Java 17

[Thread] Spinlcok

spinlockCAS는 단순한 연산 뿐만 아니라, synchronized, Lock(ReentrantLock) 없이 락을 구현하는데 사용할 수도 있다.스레드를 대기없이 lock을 구현하는 방법인데, 이를 spinlock이라고 한다.public class SpinLockBad { private volatile boolean lock = false; public void lock() { log("락 획득 시도"); while (true) { if (!lock) { // 락 사용 여부 확인 sleep(100); // 문제 상황 확인, 스레드 대기 lock = true; // 어떤 스레드가 락을 획득한 ..

Java 2024.09.08

[Thread] Lock, ReetrantLock

ReetrantLock자바 1.0부터 지원하기 시작한 synchronized와 BLOCKED 상태를 통한 임계 영역 관리의 한계를 극복하기 위해 자바 1.5부터 Lock 인터페이스, ReentrantLock 구현체를 제공한다. package java.util.concurrent.locks;import java.util.concurrent.TimeUnit;public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; vo..

Java 2024.09.07

[Thread] LockSupport

Lock supportLock support는 synchronized의 단점을 보완하기 위해 Java1.5부터 추가된 라이브러리 패키지다. synchronized의 단점은무한대기특정 시간까지만 대기하는 타임아웃X중간에 인터럽트X공정성락이 돌아왔을 때 BLOCKED 상태의 여러 스레드 중에 어떤 스레드가 락을 획득할 지 알 수 없어서 특정 스레드는 오랜기간 동안 락을 획득하지 못할 수 있다.Lock Support의 기능LockSupport는 스레드를 WAITING 상태로 변경한다. WAITING 상태는 누군가가 다시 상태를 변경하지 않으면 계속 대기상태고 CPU 실행 스케줄링에 들어가지 않는다.park() : 스레드를 WAITING 상태로 변경한다.스레드를 대기 상태로 둔다. parkNanos(nanos..

Java 2024.09.06

[Thread] CAS 연산

CAS 연산lock 기반 방식(synchronized)의 문제점은 데이터를 보호하기 위해 락을 사용하게 된다. 락은 특정 자원을 보호하기 위해 스레드가 해당 자원에 대한 접근하는 것을 제한한다. 락이 걸려 있는 동안 다른 스레드들은 해당 자원에 접근할 수 없고, 락이 해제될 때까지 대기해야 한다. 그리고 락을 획득하고 반납하는 과정에서도 시간이 소요된다. 락이 있는지 확인한다.락을 획득하고 임계 영역에 들어간다.작업을 수행한다.락을 반납한다. 1억번의 연산을 수행한다면 4가지 과정을 반복하게 된다. 이러한 문제를 해결하기 위해 락을 걸지 않고 원자적인 연산을 수행할 수 있는 방법이 CAS(Compare-And-Swap, Compare-And-Set) 연산이라 하고, 락을 사용하지 않기 때문에 lock..

Java 2024.09.03

[Thread] Atomic, volatile, synchronized 성능 비교

원자적 연산원자적 연산은 중단되지 않고, 다른 연산과 간섭 없이 완전히 실행되거나 전혀 실행되지 않는 성질을 가지고 있다. 멀티 스레드 상황에서 다른 스레드의 간섭 없이 안전하게 처리되는 연산이라는 뜻이다. volatile int i = 0;// 원자적 연산 -> 여러 스레드가 접근해도 i에 값만 할당하니까 문제 없다.i = 1;// 원자적 연산이 아니다 -> 여러 스레드가 동시에 접근하면 문제가 생길 수 있다.i = i + 1; Java에서 제공하는 Atomic 객체 성능 비교BasicInteger -> 아무 키워드, 아무것도 사용하지 않고 int값을 증가 시킨다.VolatileInteger -> 메모리 가시성을 비교 하기 위해 int 변수에 Volatile 키워드만 추가하고 int 값을 증가시킨다...

Java 2024.09.03

[Thread] synchronized

synchronized멀티스레드를 사용할 때 가장 주의해야 할 점은, 같은 리소스에 여러 스레드가 동시에 접근할 때 발생하는 동시성 문제다. 여러 스레드가 접근하는 자원을 공유 자원이라 하고, 멀티스레드를 사용할 때는 이런 공유 자원에 대한 접근을 적절하게 동기화(synchronized)해서 동시성 문제가 발생하지 않게 방지 해야 한다.public class BankAccountV1 implements BankAccount { private int balance; public BankAccountV1(int initialBalance) { this.balance = initialBalance; } @Override public boolean withdraw(int ..

Java 2024.09.02

자바 예외 재정의 규칙

자바 예외 재정의 규칙Runnable 인터페이스의 run() 메서드를 구현할 때 InterruptedException 체크 예외를 thrwos 할 수 없는 이유는 자바의 규칙 때문이다.public interface Runnable { void run();}자바에서 메서드를 재정의 할 때, 재정의 메서드가 지켜야할 예외 관련 규칙은체크 예외부모 메서드가 체크 예외를 던지지 않는 경우, 재정의된 자식 메서드도 체크 예외를 던질 수 없다.자식 메서드는 부모 메서드가 던질 수 있는 체크 예외의 하위 타입만 던질 수 있다.언체크(런타임) 예외예외 처리를 강제하지 않으므로 상관없이 throw 할 수 있다.Runnable 인터페이스의 run() 메서드는 아무런 체크 예외를 throw 하지 않는다. 따라서 Run..

Java 2024.09.01

Java - Reactor_pattern

Reactor patternReactor pattern은 동시에 들어오는 요청을 처리하는 이벤트 핸들링 방식이다.Service handler는 요청을 demultiplexing하여 동기적으로 request handler에 전달한다.Accept, read, write와 같은 이벤트들을 한 곳에 등록하여 관찰하고, 준비된 이벤트를 request handler에게 전달한다.이는 Java NIO의 selector를 이용한 처리와 유사한 방식으로 볼 수 있다.Reactor pattern의 구현Reactor, Selector, Acceptor, EventHandler 구현체로 구성되며, Acceptor는 EventHandler 구현체의 일부이고 accept 이벤트에만 집중한다.EventHandler 구현체는 rea..

Java 2024.05.07

Java NIO - Selector

Java NIO의 문제점은 main스레드에서 accept가 완료되었는지 주기적으로 확인하고, 각각의 스레드에서 read 가능한지 주기적으로 확인해야한다.채널의 상태를 개발자가 수동으로 관리해야하고 코드의 복잡성이 증가한다. main 스레드 하나에서 이벤트를 추적 관리하기 때문에 트래픽이 동시에 많이 생기는 경우 연결 처리가 순차적으로 발생하여 성능이 감소할 수 있다.이러한 동기 non-blocking에서 주로 발생하는 문제점이 busy-wait 문제이다.계속해서 callee 스레드의 작업 결과가 궁금하기 때문에 주기적으로 결과를 확인해야 한다. 이때, loop를 계속해서 돌면서 원하는 자원을 얻을 때까지 확인을 하기 때문에, 지속적인 cpu를 점유하게 되고, cpu의 낭비가 생기는 문제가 발생한다.그래서..

Java 2024.05.05

Java - Direct, Heap Buffer SelectableChannel

DirectBuffer, HeapByteBufferJava IO의 단점 중 커널 버퍼에 직접 접근이 불가능해서 메모리 copy가 발생해 CPU 자원이 소모된다는 단점이 있다.JavaNIO 에서는 이런 단점을 보완한 DirectByteBuffer, HeapByteBuffer를 제공한다. DirectByteBuffer의 특징은 native메모리(off-heap)에 저장하고, 커널 메모리에서 복사를 하지 않으므로 데이터를 읽고 쓰는 속도가 빠르며 비용이 많이 드는 system call을 사용하므로 allocate, deallocate가 느리다는 특징을 가지고 있다.HeapByteBuffer의 특징은 JVM heap 메모리에 저장하고 byte array를 랩핑하고 있다. 커널 메모리에서 복사가 일어나게 되는데..

Java 2024.04.25
반응형