1

동일한 개체를 수정하는 두 개의 스레드가 있고 MyObject라고 말하면 개체를 동기화했습니다. 그러나 스레드 중 하나에서 다른 객체가 수정되어 MyObject를 호출해야합니다.자바에서 스레드 동기화

e.e.

public void run(){ 
    synchronized(MyObject){ 
      ... 
      anotherObject.modify();//<----calls MyObject 
      ... 
    } 
} 

이로 인해 ConcurrentModificationExceptions이 발생합니다. 이 문제를 해결하는 방법을 모르겠습니다. 동기화하지 않으면 두 스레드가 MyObject를 호출 할 때 예외가 발생합니다. 이 문제를 어떻게 해결할 수 있습니까?

업데이트 : 코드는 Android 기기 용입니다. 이전에는 언급하지 않았습니다. Android 관련 특정 객체가 없기 때문입니다. 47 : 43.660 : ERROR/AndroidRuntime (5258)는 처리되지 않는 처리기 47 : 출사 메인 쓰레드 의한 캐치되지 않는 예외 02-03 02 로그 캣 출력

02-03 02 매우 유용하지 않다 43.670 : 오류/AndroidRuntime (5258) : java.util.ConcurrentModificationException 02-03 02 : 47 : 43.670 : ERROR/AndroidRuntime (5258) : java.util.AbstractList에서 $ SimpleListIterator.next (AbstractList.java:64) 02- 03 02 : 47 : 43.670 : ERROR/AndroidRuntime (5258) : com.jjg.myapp.gameunit.findEnemy (MoveableUnit.java:656) // < ---이 방법에서 Gamestate의 컬렉션은 02-03 02을 통해 반복됩니다. : 47 : 43.670 : ERROR/AndroidRuntime (5258) : com.jjg.myapp.gameunit.update (GameUnit.java:416)에서

내가 동기화하려고했던 대상은 본질적으로 gs라는 GameState입니다. 그것은 ArrayLists, 배열 및 다른 객체의 구색을 수용합니다. gs는 정적이 아닙니다.

문제가 발생하는 경우 위의 방법은 다음과 같습니다

for(GameUnit gu : this.getBase().getGameState().getAllUnits()){//<---this is the problem line. 
//do some stuff... 
} 

getAllUnits는 GameUnits의 ArrayList를 반환 (메소드를 호출 GameUnit를 포함하여 - 어떤 물체가 삭제되거나 만들어지면 내가 반복자를 필요가 없습니다).

+6

실제 코드와 예외 스택 추적을 표시하십시오. ConcurrentModificationException은 다중 스레드와 아무 관련이 없습니다. –

+2

귀하의 상황과 관련된 구체적인 조언을 제공 하기엔 너무 세세한 부분이 있습니다. 실제 코드를 보여주십시오. – NPE

+0

업데이트했습니다. 업데이트 된 정보가 유용하길 바란다. –

답변

1

당신은 정말이 같은 질문을 하셨 겠죠 : Thread-safe iteration over a collection합니다. 당신이 수정하고 어디든지 또는

for(GameUnit gu : new ArrayList<GameUnit>(this.getBase().getGameState().getAllUnits())) 

이, 당신은 또한 동기화가 작동하려면 콜렉션 자체 (즉,주의에 동기화 할 수 있습니다 :

가장 간단한 해결책은 그것을 통해 반복하기 전에 목록을 복사하는 것입니다 "모든 단위"목록) :

ArrayList<GameUnit> units = this.getBase().getGameState().getAllUnits()) 
synchronized (units) { 
    ... 
} 
1

ConcurrentModificationException은 반복자를 사용하는 동안 컬렉션을 수정하면 종종 throw됩니다. - 그래서 내 이름을 오도하고 잘못 된 문제를 찾는다.

+0

반복기를 사용하면 Con.Mod.Ex.가 막히지 않는가? 나는 혼란스러워. –

+3

@JJG : 실제로 iterator가 수정을 감지하면 예외를 던지는 iterator입니다. 반복자를 사용하여 컬렉션에서 '제거'할 수 있다는 사실을 혼동하는 경우가 있습니다. – Cratylus

+0

BTW : foreach 루프가 있습니다. 인터 레이터를 기반으로합니다. – Ralph

0

동일한 개체를 수정하는 두 개의 스레드가 있습니다. MyObject 및 이 개체를 동기화하도록합니다.

아니요. 단 하나의 스레드가 수정 중입니다. MyObject 다른 스레드가 차단되었습니다.

그러나 스레드 중 하나에서 다른 개체가 수정되고 따라서 은 MyObject를 호출해야합니다.

자물쇠가 대여 중이므로 자물쇠가있는 스레드가 다시 이동합니다.

덧글에 게시 된 코드는 실제로 예외를 얻기 위해 수행 한 작업을 보여주지 않습니다.

MyObject a Collection? 즉, 적절한 동기화가없는 다른 곳에서이 컬렉션을 동시에 수정하고 있습니까?
또는 iterating?
이 경우 예외가 발생합니다.

0

이 작업은 수행 할 수 없으며 순환 논리입니다.

스레드를 모두 없애고 명백한 평가 순서를 결정하거나 다른 방법으로 데이터를 공유해야합니다.

한 가지 전략은 다음과 같이 별도의 실행 가능한 스레드로 호출 "anotherObject.modify"를 넣어하는 것입니다

SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     anotherObject.modify(); 
    } 
    });