Value-based 클래스들이 lock을 하는데 사용되선 안됩니다

 

⚠️주의⚠️: 해당 문서는 역자의 능력 부족으로 인해 의역이 많이 들어갔습니다. Contribution을 환영합니다.

문서에 따르면,

value-based class에서 같은 값을 가리키는 두개의 참조 객체를 다르게 구분한다면, 예상치 못한 문제가 발생할 수 있습니다. 특히, 그런 상황에서 synchronization 하거나 hash 값으로 동등성을 체크하려 한다거나, 직렬화 하려할 때 등에 문제가 발생합니다.

이는 value-based class가 단순히 value 타입의 wrapper가 되는 것을 의도하고 만들어졌기 때문입니다.

value-based class의 인스턴스

  • 접근 가능한 생성자가 없지만, 대신 반환된 인스턴스의 ID에 대해 약속하지 않는 팩토리 메서드를 통해 인스턴스화됩니다

이는 즉, value-based class의 인스턴스에 lock을 걸려는 사람이, 당신밖에 없는, 유일한 사용자라고 보장하지 못한다는 의미입니다. 따라서 코드가 경합을 일으키고 deadlock 문제에 노출됩니다.

Java 8에서 이 규칙을 위반한다고해서 코드가 실제로 깨진다고 할 수 는 없습니다. 하지만 그렇다고 제대로 동작할 것이라고 보장 할 수도 없습니다.

이 규칙은 이미 알려진 value-based classsynchronization에 사용될 때 경종을 울립니다.

  • java.time 패키지 내의 Clock을 제외한 모든 클래스
  • 캘린더의 대인이 될 수 있는 Date 클래스: HijraDate, JapaneseDate, MinguDate, ThaiBuddistDate
  • Optional 클래스들: Optional, OptionalDouble, OptionalLong, OptionalInt

참고: 이 규칙은 프로젝트의 sonar.java.source의 값이 8보다 낮은 경우(java8) 검사하지 않습니다.

규칙을 어긴 코드

Optional<Foo> fOpt = doSomething();
synchronized (fOpt) {  // 규칙을 어긴 코드
  // ...
}

같이보면 좋은 자료

  • Value-based classes java.util.Optional and java.time.LocalDateTime같은 클래스를 보고 Value-based class 라고 부릅니다.

<역>역>

@Test
public void test() {
  Optional<String> a = Optional.of("foo");
  Optional<String> b = Optional.of("foo");
  System.out.println(a == b); // 출력값: false
  System.out.println(a.equals(b)); // 출력값: true
}

위 코드에서 a와 b는 “foo”라는 immutable을 참조하고 있어서 같은 value를 가르키고 있습니다. Optional은 value-based class이기 때문에, 원칙상 내부 값이 같은 a와 b는 같은 값입니다. 하지만 a와 b의 참조가 다릅니다. 그래서 a == b는 false를 반환하지만, Optional이 equals를 재정의하여 내부 값이 같으면 같은 값으로 인지하도록 해두었으므로 a.equals(b)는 true를 반환합니다.


If you like SONARKUBE, don’t forget to give me a star. :star2:

원문으로 바로가기

Star This Project