[ 11 장 : 동시성 ]

⭐ 스레드 : 여러 활동을 동시에 수행할 수 있게 해준다.

하지만, 동시성 프로그래밍은 단일 스레드 프로그래밍보다 어렵다.
잘못될 수 있는 일이 늘어나고 문제를 재현하기도 어려워지기 때문이다.

=> 동시성 프로그램을 명확하고 정확하게 만들고 잘 문서화해보자 !

synchronized 키워드

동기화의 목적

  1. 일관성이 깨진 상태를 볼 수 없게 한다.
  2. 동기화된 메서드나 블록에 들어간 스레드가 같은 락의 보호하에 수행된 모든 이전 수정의 최종 결과를 보게 해준다.
public class Counter {
    private int count = 0; // 원자적 읽기/쓰기 가능

    public void increment() {
        count++; // 원자적이지 않음
    }

    public int getCount() {
        return count; // 원자적 읽기 가능
    }
}

longdouble 외의 변수를 읽고 쓰는 동작은 원자적(atomic)이다.

❓ 원자적이라는 것은 어떤 것인가?
- 여러 스레드가 같은 변수를 동기화 없이 수정하는 중이라도, 항상 어떤 스레드가 정상적으로 저장한 값을 온전히 읽어옴을 보장한다라는 뜻이다.

❓ 왜 `long` 과 `double` 의 변수를 읽고 쓰는 것은 원자적이지 않은가?
- `int`와 `float`는 보통 4바이트 크기이므로 대부분의 시스템에서 원자적으로 읽고 쓸 수 있다.
- `long`과 `double`은 8바이트 크기로, 일부 시스템에서는 8바이트 크기의 데이터를 원자적으로 처리할 수 없기 때문에, 이 경우 읽기와 쓰기가 원자적으로 보장되지 않는다.
		
		=> `volatile` 을 사용하면 가능하다!

자바 언어 명세는 스레드가 필드를 읽을 때 항상 수정이 완전히 반영된 값을 얻는다고 보장하지만, 한 스레드가 저장한 값이 다른 스레드에게 보이는가는 보장하지 않는다.

💡 동기화는 배타적 실행뿐 아니라 스레드 사이의 안정적인 통신에 꼭 필요하다 !

공유 중인 가변 데이터를 비록 원자적으로 읽고 쓸 수 있을지라도 동기화에 실패하면 처참한 결과로 이어질 수 있다.