상호 배제를 통한 동기화의 개념을 선행하고 보면 이해하는데 도움이 됩니다.
현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터에 접근 할 수 없도록 막는 개념
메서드 앞에 키워드
동기화 문제를 해결하는데 가장 간단하고 확실하면서 무식한 방법입니다.
여기서 무식하다 함은 synchronized로 인하여 객체에 포함된 다른 모든 synchronized의 접근 까지 lock이 걸리기 때문입니다.
public synchronized void method(){
// 코드
}
@Synchronized
fun syncMethod() = run {
}
인스턴스 사용: (메서드) { 구현 }
private Object obj = new Object();
public void exampleMethod(){
synchronized(obj){
//코드
}
}
특정 Statements에 대한 Locking을 관리하는 것을 볼 수 있다.
Syncronized를 사용할 경우 나의 Thread가 현재 멈추어 있는지? 기아 상태에 빠진건지? 내 Thread에서 해당 Locking을 들고 있는 건지? 등등의 정보를 얻을 수 없다. Syncronized 구문을 마주했을 때 누군가 해당 객체의 Locking을 Release 하기까지 무한히 기다리는 수 밖에 없다.
그래서 Reentrant는 다양한 기능을 제공한다.
private final ReentrantLock lock = new ReentrantLock();
lock을 좀 더 다양하게 관리하거나 복잡한 상황을 컨트롤해야할 수도있습니다.
특정 시간을 기다리고 안되면 무시하고 지나가야한다던지 lock을 잡는 순서를 보장해야하는 경우가 있을수 있죠
그런경우에 사용하는것이 ReentrantLock입니다.
synchronized | Lock | |
---|---|---|
임계영역범위 | 메서드 안에 임계 영역의 시작과 끝이 존재해야한다. | lock(), unlock()으로 시작과 끝을 명시하기 때문에 여러 메서드에 나눠서 작성할 수 있다. |
경쟁상태 | (암시적인(implicit) lock): 스레드 진입권 획득 순서 보장 X | 명시적인(explicit) lock): 메서드를 호출함으로써 어떤 쓰레드가 먼저 락을 획득하게 될지 순서를 지정 O |
공정한 Lock
📌 synchronized는 공정성
을 지원하지 않는다. 반면 ReentrantLock은 생성자의 인자를 통해서 공정/불공정 설정을 할 수 있다.
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
참고
- https://tecoble.techcourse.co.kr/post/2021-10-23-java-synchronize/
- https://coding-start.tistory.com/68
- https://tourspace.tistory.com/54
- https://kadosholy.tistory.com/123
- https://jgrammer.tistory.com/entry/Java-%ED%98%BC%EB%8F%99%EB%90%98%EB%8A%94-synchronized-%EB%8F%99%EA%B8%B0%ED%99%94-%EC%A0%95%EB%A6%AC
- https://velog.io/@backtony/Java-synchronized-%EB%8F%99%EA%B8%B0%ED%99%94
- https://jamssoft.tistory.com/199
차이점