BackEnd/Java

[Java] synchronized - 동기화

kangminhyuk1111 2024. 8. 19. 10:42

한번의 하나의 스레드만 사용할 수 있게 만든다.

둘 이상의 스레드가 공동의 자원을 공유하는 경우, 순서에 맞춰서 접근이 필요하고  스레드에 대한 동기화를 이용해서 하나의 자원에 접근하려 할 때, 주어진 순간에는 오직 하나의 스레드만 접근 가능하도록 하는 것

모든 객체는 내부에 자신만의 lock을 가지고 있다.
- 모니터 락 이라고 부른다
- 객체 내부에 있어서 확인이 어렵다

스레드가 synchronized 키워드가 있는 메서드에 진입 하려면 반드시 해당 인스턴스의 락이 있어야 한다. 

이 상황을 실제 우리가 살아가는 상황에 대입해볼 수 있다.

(저는 개인적으로 락 = 키 라고 생각하는것이 이해가 빨랐습니다.)

만약 우리가 화장실에 들어가야 하는 상황이라고 가정한다. 화장실에 들어가려고 하는데, 
A가 이미 들어가서 사용중이다.
- 이 상황이 A가 synchronized 키워드가 있는 메서드에 먼저 다른 스레드가 진입해서 락을 가져가서 사용하고 있는 상황이다.

그리고 A가 다 사용하고 나와서 내가 이제 들어가서 사용해야 한다고 가정한다.
그렇다면, 나는 락을 챙겨서 화장실에 들어가서 볼일을 보고 다음 사람한테 넘길 것이다.
- A가 사용했으니 이제는 내가 들어가서 synchronized 키워드가 있는 메서드를 사용하고 그다음 스레드에 넘겨주는 행위를 하는 것이다.

이렇게 이용하게 된다면, 만약 A가 사용하고 나왔는데 변기가 막혔다면 검증 단계에서 오류를 발생시킬 것이다. 
예를들어, open() 메서드로 만약 화장실 문을 열고 들어갔는데 이 메서드가 "변기가 막혀있습니다" 라는 exception을 발현한다면 검증이 실패되는 것이다.

결론적으로 synchronized 키워드는 멀티스레드 상황에서 다른 스레드가 synchronized를 사용할 때 접근하지 못하게 제한하는 역할이고, 이것은 락을 통해 이루어 진다고 설명할 수 있다.

참고 : 락을 획득하는 순서는 보장되지 않는다.

synchronized의 가장 큰 장점이자 단점이 결국 "하나의 스레드만 사용 가능하다." 이다.

장점은 안전성이 보장될 것이지만, 단점으로 성능이 떨어질 것이다.

그렇기 때문에 synchronized는 반드시 필요한 구간에서만 사용해야 한다. 
동시성 문제를 해결하기 위해서는 어쩔 수 없다. 하나를 챙기면 하나를 포기해야 된다.

과도한 synchronized는 성능 저하를 일으키기 때문에 반드시 필요할 때만 사용

반응형