더북(TheBook)

컴파일러가 모든 동시 접근 오류를 잡아낼 것으로 기대하지 말자. 변경 금지는 오직 지역 변수에만 해당한다. 만일 matches가 람다를 감싸고 있는 클래스의 인스턴스 변수 또는 정적 변수라면 (결과가 정의되어 있지 않더라도) 오류가 보고되지 않는다.

또한, 공유 객체 변경은 말이 안 되는 것 같지만 규칙에 맞는 일이다. 예를 들면, 다음과 같다.


List<Path> matches = new ArrayList<>();

for (Path p : files)

new Thread(

() -> { if (p가 어떤 프로퍼티를 포함하면) matches.add(p); }).start();

// matches를 변경하는 일이 규칙에 맞지만 안전하지 않다.


 

변수 matches사실상 finaleffectively final임을 주목하기 바란다(사실상 final 변수란 초기화된 후 새로운 값을 전혀 대입받지 않은 변수를 말한다). 예에서는 matches가 항상 같은 ArrayList 객체를 참조한다. 하지만 해당 ArrayList 객체 자체는 변경되었기 때문에 스레드에 안전하지 않다. 따라서 여러 스레드에서 add를 호출하면 결과는 예측할 수 없다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.