이것은 Java의 일반적인 동시성 문제에 대한 일종의 설문 조사입니다. Swing의 전형적인 교착 상태 또는 경쟁 조건 또는 EDT 스레딩 버그가 그 예입니다. 가능한 광범위한 문제와 가장 일반적인 문제에 관심이 있습니다. 따라서 댓글 당 Java 동시성 버그에 대한 특정 답변을 하나 남겨두고 발생한 버그가 있으면 투표하십시오.
답변
내가 본 가장 일반적인 동시성 문제는 하나의 스레드로 작성된 필드가 다른 스레드로 표시 되지 않는다는 것을 인식 하지 못한다 는 것 입니다. 이것의 일반적인 응용 프로그램 :
class MyThread extends Thread {
private boolean stop = false;
public void run() {
while(!stop) {
doSomeWork();
}
}
public void setStop() {
this.stop = true;
}
}
만큼 정지로하지 휘발성 이나 setStop
하고 run
있지 않습니다 동기화 이 작동하도록 보장 할 수 없습니다. 이 실수는 99.999 %에서 특히 끔찍합니다. 독자 스레드가 결국 변화를 볼 수 있기 때문에 실제로는 문제가되지 않습니다. 그러나 우리는 그가 얼마나 빨리 그것을 보았는지 모릅니다.
답변
내 # 1 가장 고통스러운 때 동시성 문제는 지금까지 발생한 두 개의 서로 다른 오픈 소스 라이브러리는 다음과 같이 뭔가를했다 :
private static final String LOCK = "LOCK"; // use matching strings
// in two different libraries
public doSomestuff() {
synchronized(LOCK) {
this.work();
}
}
언뜻보기에 이것은 아주 간단한 동기화 예제처럼 보입니다. 하나; Strings는 Java 로 인턴 되기 때문에 리터럴 문자열 "LOCK"
은 java.lang.String
서로 완전히 분리되어 선언되었지만 동일한 인스턴스로 나타납니다 . 결과는 분명히 나쁩니다.
답변
하나의 고전적인 문제는 동기화하는 객체를 동기화하는 동안 변경하는 것입니다.
synchronized(foo) {
foo = ...
}
그런 다음 다른 동시 스레드가 다른 개체에서 동기화되고이 블록은 예상 한 상호 배제를 제공하지 않습니다.
답변
일반적인 문제는 여러 스레드에서 Calendar 및 SimpleDateFormat과 같은 클래스를 동기화없이 사용하는 것입니다 (정적 변수로 캐싱). 이러한 클래스는 스레드로부터 안전하지 않으므로 다중 스레드 액세스는 궁극적으로 일관성이없는 상태에서 이상한 문제를 일으킬 수 있습니다.
답변
에 의해 반환 된 객체 , 특히 반복 또는 여러 작업 중에 올바르게 동기화 되지 않음 Collections.synchronizedXXX()
:
Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());
...
if(!map.containsKey("foo"))
map.put("foo", "bar");
그건 잘못된 . 하나의 작업에도 불구하고 synchronized
, 호출을 맵의 상태 contains
와는 put
다른 스레드에 의해 변경 될 수있다. 그것은해야한다:
synchronized(map) {
if(!map.containsKey("foo"))
map.put("foo", "bar");
}
또는 ConcurrentMap
구현 :
map.putIfAbsent("foo", "bar");
답변
이중 확인 잠금. 전반적으로.
BEA에서 일할 때의 문제를 배우기 시작한 패러다임은 사람들이 다음과 같은 방식으로 싱글 톤을 검사한다는 것입니다.
public Class MySingleton {
private static MySingleton s_instance;
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) { s_instance = new MySingleton(); }
}
return s_instance;
}
}
다른 스레드가 동기화 된 블록에 들어가서 s_instance가 더 이상 null이 아니기 때문에 이것은 작동하지 않습니다. 따라서 자연스런 변화는 다음과 같습니다.
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) {
if(s_instance == null) s_instance = new MySingleton();
}
}
return s_instance;
}
Java 메모리 모델이 지원하지 않기 때문에 작동하지 않습니다. s_instance를 휘발성으로 선언해야 작동하며 Java 5에서만 작동합니다.
Java 메모리 모델의 복잡성에 익숙하지 않은 사람들은 이것을 항상 혼란스럽게 한다 .
답변
아마도 정확히 당신이 요구하는 것은 아니지만, 내가 직면 한 가장 빈번한 동시성 관련 문제는 (아마도 일반적인 단일 스레드 코드에서 발생하기 때문에)
java.util.ConcurrentModificationException
다음과 같은 것들로 인해 발생합니다.
List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
for (String string : list) { list.remove(string); }