2010-05-08 8 views
1

간단한 작업 대기열을 구현하는 데 문제가 있습니다. 몇 가지 분석을하는 중, 나는 미묘한 문제에 직면 해있다. 작업 대기열은 일반 연결 목록에 의해 지원됩니다. 코드는 본 간체 같다 : 이것은 간체 같은간단한 작업 대기열 구현시 문제가 발생했습니다.

0. while (true) 
    1. while (enabled == true) 
     2. acquire lock on the list and get the next action to be executed (blocking operation) (store it in a local variable) 
     3. execute the action (outside the lock on the list on previous line) 
    4. get lock on this work queue 
     5. wait until this work queue has been notified (triggered when setEnabled(true) has been callled) 

는 setEnabled (E) 동작을 보이는이 작동하더라도

enabled = e 
if (enabled == true) 
    acquire lock on this work queue and do notify() 

은 교착 상태가 발생되는 조건이있다. 그것은 다음과 같은 드문 상황에서 발생합니다 작업이는, setEnabled, 단계 (3) 동안 실행되는 동안

  • (false)를
  • 단계는 (4), 입력 (참)는, setEnabled되기 직전
  • 가 호출이라고합니다
  • 지금 단계 (5) 계속이 작업 큐가 이미 통지하지만 우리는 그것을
  • 나는이 문제를 해결하려면 어떻게

를 놓친되어 있기 때문에, 영원히 기다리고? 나는 이것을 한동안보고 있었지만 해결책을 찾지 못했습니다.

스레드 동기화에 상당히 익숙합니다.

고마워요.

+0

특정 언어로 작업하고 있습니까? 예를 들어 .NET 언어는 대부분의 작업을 완료합니다. – ChaosPandion

+0

Java 1.1 만 지원하는 모바일 장치에서 Java로이 작업을 수행하고 있습니다. 나는 솔루션에 관심이있을뿐 아니라 (내가 쉽게 구글과 라이브러리를 다운로드 할 수 있기 때문에),하지만 내가 뭘 잘못하고 있는지 알고 싶다. 나는 실을 결코 파고 들지 못했고, 이것이 자신을 향상시킬 수있는 좋은 기회라고 생각했습니다. –

답변

0

문제가 누락 된 알림이라고 생각되면 "부 드러운"플래그와 같은 다른 부울 플래그를 저장하십시오. 그런 다음 5 단계에서 wasNotified의 동기화 검사를 수행합니다. 알림을 받았다면 1 단계를 반복하고, 그렇지 않으면 다른 알림을 기다립니다.

condition variable을 사용하여 구현할 수도 있습니다 (1.1로 제한된 경우 조건 클래스를 사용할 수 없더라도).

1

멀티 스레드 메모리 모델이 모바일 Java에서 어떻게 작동하는지 잘 모르겠습니다. Desktop Java의 경우 Java 1.5까지 심각한 버그가있는 것으로 확신합니다.

0

내가 2 명 변경에 따라 믿고 ...

은 psuedocode을 통해 실제 자바 코드로 문제를 해결하는 것이 더 쉽습니다 .. 그러나 이것은 자바 1.1 버그없는 코드 버그 있었다면 나는 놀라지 않을 것이다

setEnabled(e){ 
    acquire lock on Q{ 
     enabled = e 
     if (enabled == true) 
      do Q.notify() 
    } 
} 

2)의 5 단계로 추가 조건 : 교착 버그를 수정한다 : 다음

1) 변화는 setEnabled 활성화 = false이면

을 때까지 기다린 이 작업 대기열에 알립니다 (Q.wait())

이 방법을 사용하면 사용 가능한 플래그가 현재 작동 중지 된 경우에만 5 단계 대기가 발생합니다.

+0

두 번째 단계를 이해합니다. 그런데 왜 'enabled = e'라는 과제를 자물쇠에 넣었습니까? 이것이 필요한 이유를 찾을 수 없습니다. –

+0

@ 존 : 데드락 상황에서는 필요하지 않지만 'enabled'플래그에 대한 액세스를 적절하게 동기화합니다. 여러 스레드가 변수를 읽거나 쓰는 경우, 액세스는 동일한 잠금에서 동기화되거나 가변 변수로 선언되어야합니다. 그렇지 않으면 스레드 가시성 문제가 발생할 수 있습니다. –

0

당신은, 당신이 확인하고 루프에서 조건이 나올 때까지 기다리는 것이 확인해야한다, 그렇지 않으면 당신은 중간에 대기를 취소 할 수 있으며, 그 이후에 교착 상태가 발생할 수 있습니다

변경이 :

if (! condition) 
{ 
    wait(); 
} 

여기까지 :

while (! condition) 
{ 
    wait(); 
} 

이 내용은 wait의 설명서에서 바로 가져온 것입니다.

+0

포인터를 주셔서 감사 드리며, 나는 아직도 이유를 이해하지 못합니다.하지만 알아 내기 위해 조사를 해보겠습니다. –

0

사용할 수있을 때 작업을 처리하는 작업자와 다른 활성화 또는 비활성화 할 수있는 작업자를 만들려고합니다. 대기열이 아닌 활성화 된 상태를 중심으로 동기화해야합니다.

while (true) 
    synchronize (enabled) 
     while (!enabled) 
      enabled.wait(); 
    task = taskList.take(); 
    task.run(); 

당신이 경우 먼저를 수행하여 (당신은 가시성 문제를 받아 들일 경우)를 활성화 (! 가능)의 동기화를 줄일 수 동기화 블록 이전에 확인. 기본적으로 이중 체크 잠금으로 알려진 깨진 패러다임.

+0

왜 '대기열'대신 '사용'에 동기화해야하는지 이해하지만 큰 오류가 있습니까? '뭔가를 동기화하는 한'올바른 생각이야? '라고 생각하지 않습니까? –

+0

이 솔루션이 완전히 정확하지 않다고 생각합니다. 대기열 목록이 비어 있고 enabled가 true로 설정되어 있다고 가정 해보십시오. 이것은 taskList.take() 함수가 블로킹하고 있음을 의미합니다. 이 스레드가 대기하는 동안 setEnabled (false)가 호출됩니다. 자, 일단 작업이 추가되면, 작업은 어쨌든 실행되며, enabled 플래그는 무시됩니다. –

+0

@ 존, 원래 게시물의 구현은 동일한 결함으로 고통 받고 있습니다. 그래서 나는 작업자가 한 번 활성화 된 적어도 하나의 작업을 실행하는 것이 수용 가능하거나 의도 된 것이라고 생각했습니다. 또한 예, 당신은 무엇이든간에 동기화 할 수 있지만 동기화를 위해 대기열을 사용하면 활성화/비활성화가 목록에 추가/가져 오기 작업을 기다려야한다는 것을 의미합니다. –

관련 문제