개발하는 두더지

[Effective Java 규칙66] 변경 가능 공유 데이터에 대한 접근은 동기화하라 본문

Java,Android

[Effective Java 규칙66] 변경 가능 공유 데이터에 대한 접근은 동기화하라

덜지 2018. 11. 13. 11:49

[Effective Java 규칙66] 변경 가능 공유 데이터에 대한 접근은 동기화하라

Effective Java 2/E 책과 구글링을 통해 내용을 정리하고 개인적인 견해가 포함된 글입니다.


변경 가능한 데이터를 공유할 떄는 해당 데이터를 읽거나 쓰는 모든 스레드는 동기화를 해야 합니다. 동기화를 하지 않으면 스레드간 변경 사항이 적용될 거라고 보장할 수가 없기 때문입니다. 이런 오류들은 디버깅하기 까다롭고, 간헐적으로 발생하며, 타이밍에 민감합니다. 또한 어떤 VM이냐에 따라서 극도로 다르게 동작하기도 합니다. 


메서드나 변수에 synchronized 키워드를 이용해 스레드간 동기화를 시켜서 data의 thread-safe를 시켜줍니다. 현재 data를 사용하고있는 스레드를 제외하고 나머지 스레드들은 data에 접근할 수 없는 개념입니다.


만약 순환문 같은데 사용한다면 각 루프마다 동기화를 실행하는 비용이 발생할 수 있는데 스레드간 통신만 필요한 경우에는 그 비용을 줄이고 동기화를 할 방법이 있는데 바로 volatile 키워드를 변수에 사용하는 것입니다.

synchronized 처럼 lock, unlock 하지않고 어떤 스레드건 가장 최근에 기록된 값을 읽도록 보장시켜주기 때문에 좋은 성능을 내면서도 간결한 대안입니다.


public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) {
new Thread(() -> {
try {
int i = 0;
while(!stopReqeusted()) {
i++;
TimeUnit.MICROSECONDS.sleep(100);
System.out.println(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();

try {
TimeUnit.SECONDS.sleep(5);
requestStop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopReqeusted() {
return stopRequested;
}
}
















Comments