[TIL] 스레드와 스레드 안전성
by 달쿨프로세스와 스레드 차이점
프로세스: 일반적으로 cpu에 의해 메모리에 올려져 실행중인 프로그램을 말하며, 자신만의 메모리 공간을 포함한 독립적인 실행 환경을 가지고 있다
쓰레드: 프로세스안에서 실질적으로 작업을 실행하는 단위를 말하며, 자바에서는 JVM(Java Virtual Machine)에 의해 관리된다. 프로세스에는 적어도 한개 이상의 스레드가 있으며, Main 스레드 하나로 시작하여 스레드를 추가 생성하게 되면 멀티 스레드 환경이 된다. 이러한 스레드들은 프로세스의 리소스를 공유하기 때문에 효율적이긴 하지만 잠재적인 문제점에 노출될 수도 있다
동시성(concurrency) 이슈
여러 스레드가 동시에 하나의 자원을 공유하고 있기 때문에 같은 자원을 두고 경쟁상태(raceCondition) 같은 문제가 발생하는 것
스레드 안전성(Thread safe)
여러 스레드가 작동하는 환경에서도 문제 없이 동작하는 것을 스레드 안전하다고 말한다. 즉, 동시성 이슈를 해결하고 일어나지 않는다면 Thread safe 하다
카운트를 늘리고 조회하는 코드를 예시로 들 수 있다.
스레드A와 스레드B가 동시에 increase()메서드를 호출하여 count를 증가시켰을 때, A의 increase()로 count는 1이 되고, B의 increase()로 count는 2가 되는 것이 정상적인 동작 하지만 A와 B가 동시에 increase()메서드를 호출하게 된다면 count는 2가 아닌 1이 되는 문제가 발생한다. count를 증가시키는 로직이 count변수 값 조회, count변수에 1을 더하고 저장 두가지의 동작으로 이루어지기 때문
동시성 제어하기
암시적 Lock 사용
가장 간단하면서 쉬운 방법으로 Lock을 걸게 되면 스레드의 공유자원에 대한 독점을 허용하기 때문에 다른 스레드가 자원에 접근하지 못하고 대기하게 된다. 이는 여러 스레드가 공유자원에 동시에 접근하지 못하므로 동시성 문제를 막을 수 있지만, 하나의 스레드만 자원을 사용하므로 병렬성은 낮아지게 된다. 자바에서는 암시적 Lock은 같이 메서드에 synchronized키워드를 사용하여 구현할 수 있다. (변수도 가능하지만, 객체만 가능하다)
명시적 Lock 사용
명시적 Lock은 synchronized키워드를 사용하는 암시적 Lock과는 달리 Lock 인터페이스를 이용한다. Lock객체의 lock()메서드를 호출하여 잠그고, unlock()메서드를 호출하여 잠금을 해제한다.
volatile 사용
volatile 키워드를 사용하면 변수가 항상 메인 메모리에서 읽고 쓰이도록 보장된다. 이렇게 하면 변수에 대한 변경 사항이 다른 스레드에 즉시 반영되므로, 스레드 간의 동시성 문제를 해결할 수 있다.
volatile 키워드를 변수에 붙여주면, 해당 변수는 캐시에 저장되지 않고 메인 메모리에 항상 저장이 되는데, 바로 이 점을 이용해서 캐시 사용으로 인한 데이터 불일치를 막을 수 있다.
Concurrent 패키지 사용
자바에서 제공하는 Concurrent패키지는 동시성 문제를 해결하기 위한 다양한 클래스와 인터페이스를 제공한다.
위와 같이 ConcurrentHashMap을 사용하면 내부적으로 스레드 간의 안전한 데이터 공유를 보장하기 때문에 동시성 문제가 발생하지 않는다.
느낀 점
동시성 문제를 의식하며 코드를 작성해야 겠다고 느꼈다.
참고
https://deveric.tistory.com/m/104
'TIL' 카테고리의 다른 글
[TIL] Docker 개념 (0) | 2024.11.28 |
---|---|
[TIL] 배포 서버 시간을 한국 시간으로 설정 (0) | 2024.11.27 |
[TIL] S3 사진 외부에서 접근 안되는 문제 해결 (0) | 2024.11.25 |
[TIL] RDS 연결 시의 DB Name에 대해 알게 된 점 (1) | 2024.11.22 |
[TIL] 자바 Garbage Collection 가비지 컬렉션 이해 (0) | 2024.11.21 |
블로그의 정보
note
달쿨