스레드 안전성 여부를 이해하려고합니다. 나는 그렇다고 믿지만 누군가 최근에이 메서드의 스레드 안전성에 대해 의문을 제기했습니다.스레드 안전성 이해
의 내가 우리에게 다음과 같은 인터페이스를 구현하는 클래스주고 일부 공장 FactoryA
있다고 가정 해 봅시다 : 그래서
public abstract class MyFactory {
private ObjectA object;
public void init(ObjectA object){
_object = object;
}
}
을, 우리는 이제
public class FactoryA extends MyFactory {
static final createFactoryClass(String name) {
// ...ignorning safety checks for brevity
return MY_MAP.get(name).newInstance();
}
}
처럼, 나는 다른 몇 가지 방법을 가지고 뭔가있다 공장을 가지고 가능한 클래스지도를 돌려주는 클래스 :
public class OtherClass {
private static FactoryA _factory = new FactoryA();
private static final Map<String, SomeClass> MY_MAP = new ImmutableMap.Builder<String, MyClass>()
.put("foo", _factory.createFactoryClass("foo"));
private SomeObject myMethod(ObjectA objectA, SomeObject someObject) {
MY_MAP.get(someObject.getString()).init(objectA);
}
}
질문은 init
메서드가 스레드로부터 안전한지 여부입니다. 지도는 한 번만 초기화되므로 불변 구조에 저장되어 있어도 두 스레드가 다른 ObjectA
을 사용하여 호출하는 경우 잘못된 클래스가 잘못된 ObjectA
을 사용할 수 있습니까?
다음과 같이이 문제를 해결할 수 있습니까? 이 예에서
static void setValue(Example obj, int val) {
obj.val = val;
}
Example sharedObj = ...;
new Thread(() -> { setValue(sharedObj, 1); }).start();
new Thread(() -> { setValue(sharedObj, 2); }).start();
하지만, : 변수가 공유 객체, 즉 다음 예에서와 같은에 대한 참조가 아닌
private static synchronized myMethod(...) {}
코드에서 사용자가 클래스 간 및 형식 불일치를 참조하기 때문에 약간 혼란 스럽습니다. 하지만 진짜 질문은'init' 메소드에서하는 일에 있다고 생각합니다. – Xerillio
주어진 'MyFactory.init' 메소드는 아무 것도하지 않기 때문에 완전히 스레드 안전합니다. –
'createFactoryClass()'도 스레드로부터 안전합니다. 지도를 초기화하면 다시 쓰지 않습니다. 여기 단서는 그것이 여전히 가시적이어야한다는 것이다; 그것을'final'에 할당하는 것은 괜찮 았고'휘발성'과'synchronized'와 같이 맵 (그리고 모든 쓰기)을 볼 수있게합니다. C.f. [ "Safe Publication"] (http://stackoverflow.com/questions/801993/java-multi-threading-safe-publication) – markspace