2011-10-02 4 views
0

다른 스레드에서 잠긴 개체의 메서드를 호출 할 수 있습니까?

synchronized(object) { 
... 
} 

스레드 2에서

를 호출 할 수 있습니까 아니면 각각

synchronized(object) { 
object.method(); 
} 

을 입력해야합니까? 쓰레드 2가 쓰레드 1이 락을 잡고있는 동안 메소드를 호출하지 못하도록하려면?

제 경우에는 ConcurrentModificationExceptions을 Map을 반복하면서 얻었고 맵을 잠그면 다른 스레드에서 수정을 막으려 고했습니다. 그리고 종종 ConcurrentModificationExceptions의 이유는 반복되는 동안지도가 변경된다는 것입니다. 그러나이 경우에는 "get"문구와 하나의 메서드 호출 만 있으므로 내 사건에는 해당하지 않는다고 확신합니다. 어떤 수정도 일어날 수 없다.

미리 감사드립니다.

Binabik

+0

방법 코드를 공유하는 데주의해야합니까? 어쩌면 당신이 생각하지 못했던 무언가가있을 것입니다 – Guillaume

답변

1

Java의 동기화는 완전히 협조적입니다. 두 번째 스레드가 모니터를 가져 오려고 시도하지 않고 (그렇게하려고 시도하는 메소드에 아무 것도없는 경우) 자동으로 잠기지 않습니다.

개체가 "잠겨 있습니다"라는 것은 아닙니다. 하나의 스레드가 개체와 관련된 잠금을 소유하고 있다는 것입니다. 객체 자체는 여전히 액세스 할 수 있습니다. 잠금 장치가 필요하지 않으면 차단되지 않습니다.

하나의 스레드에서 반복을 시도하고 동일한 루프 내에서 변경하려고하면 ConcurrentModificationException을 얻을 수 있습니다.

// Not safe: will throw an exception 
for (Map.Entry<String, String> entry : map.entrySet()) { 
    if (entry.getKey().equals("foo")) { 
     map.put("bar", "Hello"); 
    } 
} 

그것은이 코드에서 무슨 일이 일어나고 있는지 것을 가능하지만 우리에게 어떤 코드를 표시하지 않은 우리가 말할 수 없다. 문제를 시연하는 짧지 만 완전한 프로그램을 제시 할 수 있다면, 우리는 현재 일어나고있는 일을 해결할 가능성이 훨씬 더 높습니다.

+1

그리고 지금 나는 바보처럼 다시 느끼고 있습니다. 왜냐하면 나는 "나는 수정이 없다"고 썼다. 그러나 수정이 발생한 클래스의 public 메서드를 호출 한 리스너에 대한 메서드 호출이있었습니다. 그러나 나의 변호에서이 수정은 아주 숨겨졌다. – Binabik

0

object.method()가 동기화 경우를 제외하고는 다른 스레드에서 호출 할 수 있습니다. 동기화되지 않은 맵에서 반복을 사용할 때는주의해야합니다. 동기화 된 맵을 사용하고 반복을 통해 동기화해야합니다. 그렇지 않으면 모든 쓰기 작업도 동기화해야합니다.

+0

Map 맵 = Collections.synchronizedMap (...)으로 맵을 초기화하면 맵의 메소드가 동기화됩니까? 그리고지도상에서 반복을 동기화하면 안전해야합니까? – Binabik

1

잠금을 획득하면 다른 스레드가 동일한 잠금을 획득하지 못합니다. 객체를 잠그지 않고 메소드에 액세스 할 수 있습니다.

ConcurrentModicationException이 발생하면 동시 수정이 발생합니다. 이런 일이 어디에서 발생하는지 잘 모르는 경우에는 더 자세히 조사해야합니다.

관련 문제