JavaBookStudy / JavaBook

책읽기 스터디
https://javabookstudy.github.io/
Apache License 2.0
19 stars 2 forks source link

[이펙티브자바_Item2] JavaBeans에서 객체 생성시 thread safe 고려해서 만드는 방법 #1

Closed kjsu0209 closed 3 years ago

kjsu0209 commented 3 years ago

JavaBeans는 객체를 만들때 setter를 호출해서 객체가 완전히 생성되기 전까지는 일관성이 깨진다고 합니다. 그러면 아래 코드와 같이 setter를 덜 호출해도 객체가 생성될 수 있다는 거죠.

class myBean{
    public myBean(){
        setA();
        // 여기서 익셉션같은게 발생하면 일관성이 깨짐
        setB();
   }
}

아마 원인이 익셉션일것같은데 이럴 경우에 스레드 안정성을 고려한 작업은 어떤게 있을지 같이 알아보면 좋을 것 같습니다😊

taxol1203 commented 3 years ago

스레드 안정성이란 여러 스레드가 객체에 접근할 때, 자원이 공유되는 것을 방지한다는 것 이라고 생각을 합니다.
여기서는 여러 스레드가 생성자의 setter를 서로 사용하려는 것이며, 이게 문제가 되지 않을까 추측을 해봅니다.
스레드 안정성을 보장하기 위한 작업은 synchronized, volatile 변수, 명시적 락, atomic variable와 같은 수단이 있는 것으로 알고 있으며, 해당 객체가 생성할 때 위의 수단을 통해 스레드 안정성을 보장하면 되지 않을까 생각해봅니다! 출처 : [자바 병렬 프로그래밍] 스레드 안정성

kjsu0209 commented 3 years ago

JavaBeans가 thread safe하지 않다고 하는 이유는 보통 여러 스레드에서 JavaBeans 객체에 한꺼번에 접근해 값을 바꾸는 데서 일관성이 깨지기 때문이라고 합니다. 이때는 setter에 synchronized 키워드를 붙이면 해결된다고 합니다.

객체가 덜 생성되었을 때 문제를 해결하는 방법에는 어떤게 있을까요? 수업시간에 배웠던 바로는 객체 생성(new 키워드 작동) 과정이

  1. 메모리 할당
  2. 디폴트 값 초기화
  3. 명시적 값 초기화
  4. 생성자 호출

이렇게 되어 있다고 하는데요.

한 스레드가 JavaBeans 객체를 생성해서 1을 완료하기만 했다면 다른 스레드에서 JavaBeans객체 인스턴스 주소값에 접근이 가능해서 문제가 생기는게 아닐까 추측합니다.

이럴 때는 atomic variable을 만들어서 생성자가 호출되었을때 락을 걸고, 작업을 모두 마쳤을 때는 락을 풀게 하면 될 것 같아요. 락이 걸려 있을 동안에는 다른 스레드에서 getter를 통해 인스턴스 주소값에 접근하더라도 원하는 작업을 못하게 하면 되지 않을까요?

다른 의견 환영합니다🤔

daebalprime commented 3 years ago

위의 'thread safe'에 덧붙이자면, 자바빈즈 패턴이 Thread safe를 보장하지 못하는 이유는 객체 생성을 완료하기 위해서 의도하고자 하는 여러 개의 세터들을 모두 호출하여야 논리적으로 무결한 객체가 완성이 되지만, 문제는 특별한 조치를 취하지 않는 이상 하나의 객체에서 만들고자 하는 여러가지 세터를 모두 호출하기 전에 다른 쓰레드에서 해당 객체에 접근이 가능하고, 다른 쓰레드는 해당 객체를 '이미 생성이 완료되어 사용하는데 문제가 없는' 객체로 인식되어 특정한 작업을 수행할 수 있기 때문에 그런 것 같습니다. 해당 책에서는 자바빈즈 패턴 대신에 빌더 패턴을 권장하고 있으니 별로 생각하지 않아도 되는 부분이 아닐까 싶네요.🤔🤔