Thread Safe 와 동시성 제어 본문
Thread Safe 란?
멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없는 것을 의미한다.
이는 하나의 메소드가 한 스레드로부터 호출되어 실행중일 때, 다른 스레드가 그 메소드를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 메소드 수행 결과가 올바르게 나오는 것으로 정의한다.
Thread Safe 는 여러가지 형태로 구현할 수 있다.
Re-Entrancy: 재진입성
어떤 메소드가 한 스레드에 의해 호출되어 실행중일 때, 다른 스레드가 그 메소드를 호출하더라도 그 결과가 각 스레드에게 올바른 형태로 반환되어야 한다.
Mutual Exclusion: 상호 배제
공유자원을 꼭 사용해야 할 경우 해당 자원의 접근을 세마포어 등의 락으로 통제한다.
Thread-Local Storage: 스레드의 지역 저장소
공유 자원의 사용을 최대한 줄여 각각의 스레드에서만 접근 가능한 저장소를 사용함으로써 동시 접근을 막는다.
Atomic Operations: 원자 연산
공유 자원에서 접근할 때 원자 연산을 이용하거나, 원자적으로 정의된 접근 방법을 사용함으로써 상호배제를 구현할 수 있다.
동시성 제어 방법
synchronized: 암시적 락
문제가 되는 메소드, 변수에 각각 synchronized 라는 키워드를 사용하는 것이다. synchronized 키워드를 변수 혹은 메소드에 걸게되면 synchronized 의 파라미터로 들어가게 되면서 스레드가 해당하는 메소드 혹은 변수에 대한 모니터를 가질 수 있게 된다.
참고로 변수에 synchronized 키워드를 걸기 위해서는 해당 변수의 타입이 객체여야만 한다. 기본형 타입에는 락을 걸 수 없다.
synchronized 가 걸려있는 부분을 기점으로 monitorenter 와 monitorexit 두 가지 instructor 가 생성된다.
스레드가 monitorenter instructor 를 가리키게 되면 모니터를 점유하게 되는데 이때, 다른 스레드들이 접근할 수 없게 되기 때문에 동시성 이슈가 발생할 가능성을 봉쇄할 수 있다. 이후 monitorexit instructor 를 가르키게 되면 모니터를 다시 반환한다.
기존에 모니터를 점유하고 있던 스레드가 모니터를 반환했기 때문에 다른 스레드들도 monitorenter 가 가능해진다. 즉, 모니터의 생명주기는 synchronized 키워드에 의존하게 된다.
synchronized 의 경우 하나의 프로세스 안에서만 보장이 되기 때문에 여러 개의 프로세스가 실행되고 있는 상황에서는 데이터의 정합성을 보장하기 어렵다. 실제 운영 환경 또한 여러 개의 서버가 돌아가는 환경이기 때문에 synchronized 를 통해서 모든 동시성 문제를 해결하기는 어렵다.
ReentrantLock: 명시적 락
synchronized 키워드 없이도 명시적으로 락을 거는 방법이다. 해당 락의 범위를 메소드 내부에서 한정하기 어렵거나, 동시에 여러 개의 락을 걸고 싶을 때 사용한다.
synchronized 키워드는 자동으로 락이 잠기고 풀리기 때문에 편리하지만, ReentrantLock 은 직접적으로 Lock 객체를 생성하여 사용하기 때문에 동기화를 시행하려는 구문을 명확하게 구분할 수 있고 조금 더 다양한 기능을 활용할 수 있다.
하지만 synchronized 와 마찬가지로 여러 대의 서버가 각각 독립된 Java 프로세스로 실행되고 있는 경우에는 ReentrantLock을 사용하여 데이터의 정합성을 보장할 수 없다. 이는 각 서버가 독립된 메모리 공간을 가지고 있기 때문에, 서로 다른 프로세스 간에는 ReentrantLock을 공유할 수 없기 때문이다.
따라서 여러 대의 서버 간에 데이터의 정합성을 보장하려면 다른 동기화 메커니즘을 사용해야 하는데, 일반적으로 분산 시스템에서는 분산 락(Distributed Lock) 또는 분산 락을 구현한 서비스를 사용하여 데이터의 일관성을 유지한다.
다음 포스트에서는 레디스를 통한 분산 락 방식에 대해서 알아보도록 하자
'Dev' 카테고리의 다른 글
Redis를 사용한 분산락 (0) | 2024.03.24 |
---|---|
운영체제와 시스템 콜 (1) | 2024.03.23 |
MySQL의 인덱스 (1) | 2024.03.16 |
3/4-way Handshake 란? (0) | 2024.02.25 |
HTTP (1) | 2024.02.24 |