공유중인 가변 데이터는 동기화 해서 사용하라

Moondy·2022년 6월 27일
1

공유중인 가변 데이터는 동기화 해서 사용하라

  • 여러 스레드가 가변 데이터를 공유한다면 반드시 동기화 해서 사용해야한다.

1. 왜?

  • 한 스레드가 수행한 변경을 다른 스레드가 못보는 일을 방지
  • 일관성을 지키며 가변 데이터 사용

2. synchronized를 이용한 동기화

  • 한 스레드가 변경하는 중이라서 상태가 일관되지 않은 순간의 객체를 다른 스레드가 보지 못하게 lock
  • 일관성을 지키며 스레드가 만든 변화를 다른 스레드에서 확인할 수 있도록 함
  • 동기화는 배타적 실행(원자성) 뿐만 아니라 스레드 사이의 안정적인 통신에 필요함
  • 쓰기와 읽기 메서드 모두 동기화 되어야 한다

3. volatile 필드를 이용한 동기화

  • 배타적 수행과는 상관 없지만 항상 가장 최근에 기록된 값을 읽게됨을 보장
  • 멀티 스레드간 통신은 지원하지만, 원자성(배타적 실행)은 보장하지 않음
  • volatile사용하면 wynchronized는 사용 불가

4. concurrent 계열의 클래스

  • lock 없이도 thread safe를 보장하는 클래스
  • 배타적 실행과 멀티스레드간 안정적인 통신 보장
  • 동기화 버전보다 성능도 우수
  • [참고] HashMap vs HashTable vs CocurrentHashMap
HashMapHashTableConcurrentHashMap
key와 value에 null 허용OXX
동기화 보장(Thread-safe)XO(메소드에 synchronized키워드가 있음)O (Map 전체에 락을 걸지 않고 Map을 여러 조각으로 쪼개 일부만 락을 건다)
추천 환경싱글 쓰레드멀티 쓰레드멀티 쓰레드
특징- 동기화 처리 하지 않아 데이터 탐색 속도 빠름
- 반면 신뢰성과 안정성 떨어짐
- 데이터 무결성 보장
- 데이터 lock으로 느림
- HashMap과 같은 구조이지만 동기화 가능
- HashMap, HashTable보다 빠름

5. 단점

  • 동기화 실패하면 응답 불가 상태에 빠지거나 안전 실패(프로그램이 잘못된 결과를 계산해내는 오류) 발생 가능
  • 디버깅 어려움
  • 간헐적이거나 특정 타이밍에 에러 발생할 수 있음

6. 결론

  • 가변데이터는 가급적 단일 스레드에서만 쓰도록 하고, 멀티 스레드간 데이터 공유하는 것을 지양하자
  • 가변데이터를 멀티 스레드에서 공유해야한다면 반드시 동기화를 하자
  • 배타적 실행과 스레드간 통신 모두 필요하다면 synchronized를 사용하자
  • 스레드간 통신만 필요하면 volatile을 이용하자
  • thread safe 한 클래스를 사용할 수 있다면 사용하자
profile
DevOps를 살짝 찍먹하는 BackEnd 개발자

0개의 댓글