Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

선진이네

[JAVA] Thread-safe란,, 본문

Language/JAVA

[JAVA] Thread-safe란,,

악마선진 2023. 10. 29. 21:42

쓰레드는 프로세스의 하위 개념으로써 프로세스에 할당된 자원을 공유한다. 프로그램을 쓰레드로 분리하면 자연스럽게 병렬성을 이용할 수 있기 때문에 애플리케이션의 성능을 향상시킬 수 있다!

Thread-safe란..!

  • 멀티 쓰레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 쓰레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없는 것을 말한다!
  • 다시 말해서, 두 개 이상의 쓰레드가 하나의 객체에 접근해도 연산 결과는 모두 동일해야한다..! 라는 느낌으로 받아들이면 될 것 같다.
  • 이건 주관적인 생각 - 트랜잭션도 A와 B가 동일한 시간에 원자에 접근했을 때 같은 결과를 확인할 수 있는 것처럼 임마도 완전 똑같은 느낌적인 느낌쓰!

Thread-safe 여부 판단 방법

보통 세 가지로 판단한다고 하는데, 일단 이해가 잘 안된다 나는…. 따라서 반례를 찾으러 가보겠다.

  1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시에 접근할 수 있는 자원을 사용하는가?

데이터베이스 커넥션 같은 경우는 여러 쓰레드에서 동시에 접근이 가능한 자원이다! 근데, 여러 쓰레드가 동시에 데이터베이스 쿼리를 실행하거나 업데이트 한다면 충돌 발생 가능성이 존재한다! 따라서 thread-safe하지 않을 수 있다!

  1. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?
  2. 부수 효과를 가져오는 코드가 있는가?

이렇게 해당 논제들에 아니다! 라는 답변이 나온다면 해당 프로그램은 Thread-safe를 보장 받지 못하는 것이다!

쉽게 말해서! 내 통장에 100만원이 있는데 민지도 가져가려하고, 범선이도 가져가려하는데! 한 놈만 가져갈 수 있는 프로그램이면 Thread-safe! 둘 다 가져갈 수 있는 프로그램이라면 Thread-safe 하지 않음!!

따라서 자원이 올바르게 공유될 수 있도록 우리는 Thread-safe를 보장해줘야 한다!

Thread-safe를 보장하기 위한 방법!

Re-entrancy(재진입성)

  • 어떤 함수가 한 쓰레드에 의해 호출되어 실행 중일 때, 다른 쓰레드가 그 함수를 호출하더라도 그 결과가 각각에게 올바르게 주어져야 한다.
  • 뭔가 말이 어려워 보이지만 결국 함수에서 사용되는 변수들을 각 쓰레드에게 독립적인(다른 쓰레드에게 영향을 주지 않음) 변수를 사용하도록 설계하라는 의미인 것 같다.
  • 내 생각 : 쓰레드끼리는 독립적으로 동작할 수 있도록 코드를 작성해야함!

Thread-local storage (쓰레드 지역 저장소)

  • 공유 자원의 사용을 최대한 줄여 각각의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는다.
  • 즉, 쓰레드끼리 공유하는 힙, 데이터 영역의 자원 접근을 최소화하고, 각 쓰레드가 독립적으로 가지는 스택 영역의 자원만 사용하도록 설계하라는 의미인 것 같다.
  • 내 생각 : 전역 변수의 코드를 줄이고, 쓰레드 내의 독립적인 변수 사용해라!

Immutable objects

  • 공유 자원을 사용한다면 불변 객체를 사용하라는 의미이다. 불변 객체는 변하지 않는 읽기 전용 자원이기 때문에 여러 쓰레드가 동시에 접근해도 쓰레드 안전성이 보장된다.
  • 만약 변경 가능한 객체를 사용한다면 공유 객체를 그대로 가져와서 사용하지 말고 새로운 객체를 생성하여 공유 자원 객체의 값들을 복사하여 사용하자.
  • 약간 DB에서 Entity를 그대로 들고 와서 사용하지 말고 DTO를 통해 사용하는 것과 비슷한 의미인 것 같다.
  • 내 생각 : 싱글톤을 사용하는 이유가 이와 유사하지 않을까요?

Mutual exclusion(상호 배제!)

  • 공유 자원을 꼭 사용해야 할 경우 해당 자원의 접근을 세마포어나 뮤텍스 등의 락으로 통제한다.
  • Java의 synchronized를 사용하라는 의미이다.
  • synchronized 키워드를 사용하면 어떤 한순간에는 하나의 스레드 만이 임계 영역(Critical Section) 안에서 실행하는 것이 보장된다.
  • 가장 많이 사용되는 방법!

그럼, 세마포어는 뭐고 뮤텍스는 뭐야! ( 간단한 차이점 표현 )

  • 세마포어
    • 화장실 남은 변기 칸 전광판이 있음
    • 다 차있으면 못 들어가고, 자리가 있으면 들어가는 느낌!
    • 공유 리소스에 접근할 수 있는 최대 허용치 만큼 동시 사용자(쓰레드, 프로세스) 접근을 허용하게 한다.
  • 뮤텍스
    • 화장실 문을 열기 위한 키가 존재! 해당 키를 사용하면서 입장
    • 뮤텍스는 Key 에 해당하는 어떤 오브젝트가 있으며 이 오브젝트를 소유한 (쓰레드,프로세스) 만이 공유자원에 접근할 수 있다.

(화장실 알고리즘으로 나는 3년째 기억 중,,,,,,너희의 우뇌에 언제나 내가 있을게)

이러한 방법을 사용하여 우리는 Thread-safe한 프로그램을 만들 수 있을 것이다!

그럼 자바에서는 어떤 식으로 Thread-safe를 지키려고 노력하는지 너무너무 궁금하지 않을 수 없을 것이다…

자바는 어떻게 쓰레드 안전성을 보장하는데!!!?

사실 공부하면서 놀랐다,, 아마 나도 너도 그리고 너의 친구도 한번쯤은 경험해본 적이 있을 것이다…!

  1. synchronized….!
@ThreadSafe
public class Sequence {
    @GuardedBy("this") private int nextValue;

    public synchronized int getNext() {
        return nextValue++;
    }
}

여기서 중점은 ! synchronized라는 녀석!

동기화 개념으로 많이들 알고 있을 것이다.. 심지어 우리 공통 코드에 있음,,!

synchronized를 달고 있는 녀석들은 락을 공유한다!

위에 언급했던 상호 배제를 임마들끼리 알아서 하고 있던 것이다!

따라서 해당 메소드에 접근하는 녀석들은 락이 공유되면서 차례차례 이쁘게 저 nextValue라는 녀석에 접근하고 있던 것이었던 것이었음..! ㅋㅋ 말도 안돼

 

두번째,,, 자료구조

Hashtable, ConcurrentHashMap, AtomicInteger, BlockingQueue

등등의 자료구조들!!

임마들 안에 파헤쳐보면, synchronized를 달고 있음,,,! 따라서 알아서 얘네가 락 걸어주고 이쁘게 데이터를 줄 수 있었던 것임,,,! ㅋ 대박쓰

자바에는 참 똑똑한 기능들이 많은 것 같다.

취업이 힘들어도, 성장중인 나 그리고 너를 보며 난 오늘도 달린다…IF I DIE Tomorrow..

 

삼, 아까 말했듯이 불변 객체 사용!

스레드 안전성을 보장하는 마지막 방법으로 불변객체를 사용하는 방법이다.

불변객체란 객체가 선언된 이후로는 변경할 수 없는 객체임을 뜻하는데 자바에서는 대표적으로 String이 있다. 그렇다면 String은 기본적으로 스레드에 안전할까? 그렇다. String은 스레드에 안전하다.

불변 객체는 변하지 않으니까, 언제 어디서 내가 혹은 너가 혹은 우리 인포누나가 혹은 우리 식당이모님이 혹은 우리 미래의 배우자가 보더라도 똑같은 값을 볼 수 있잖아!

따라서 Thread-safe한 넘인거지!

 

이렇게 3가지 이외에도 많은 방법이 있지만, 자바는 이런 형식으로 쓰레드 안전성을 보장하곤 한다! 시간 많을 때, 임마를 코드로 적용시키는 것도 너무나도 재미있지 않을 수 없을 듯!

'Language > JAVA' 카테고리의 다른 글

[JAVA] 예외 처리 못하겠으면, 이대로만 해  (0) 2023.09.08
[JAVA] Map - getOrDefault란,  (0) 2023.09.07
[JAVA] XML Parsing  (0) 2023.01.30
[JAVA] Lamda Expression  (0) 2023.01.28
[JAVA] 입출력 정리  (0) 2023.01.28