2011-03-15 3 views
3

이중 버퍼링을 사용하는 스레드 된 응용 프로그램을 만들고 잠재적 인 교착 상태를 피하려고합니다. 주 아이디어는 스왑 버퍼 스레드가 쓰기 및 읽기 스레드를 잠그는 것입니다. 그러나 스왑 버퍼 스레드가 빠르므로 잠금이 오래 잠긴 상태로 유지되지 않습니다. 쓰기 및 읽기 스레드는 느리지 만 다른 뮤텍스를 잠그기 때문에 시간 조각을 효율적으로 (목표) 공유합니다. 제 질문은이 디자인에 잠재적으로 교착 상태가 있습니까?C 이중 버퍼 구현 교착 상태?

  • 3 스레드 ... 스레드 A, 스레드 B 및 C
  • 2 뮤텍스 ... 전면 뮤텍스와 뒤로 뮤텍스를 스레드.

  • 스레드 A는
  • 스레드 B 버퍼 스왑 백 버퍼를 채운다.
  • 스레드 C는 프론트 버퍼를 사용합니다.

  • 스레드 A가 theBackMutex 소요 백 버퍼를 채우고, theBackMutex 릴리즈.
  • 스레드 C는 theFrontMutex를 사용하고 프론트 버퍼를 사용하여 theFrontMutex를 해제합니다.
  • 스레드 B가, theBackMutex, theFrontMutex는, 버퍼를 스왑합니다 theBackMutex을 출시, theFront 뮤텍스를 해제

void *fill_back_buffer() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //should we get new data for back buffer? 
     pthread_cond_wait(&theBackBufferRefresh, &theBackMutex); 
     //fill back buffer 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey we done filling the back buffer! 
     pthread_cond_signal(&theBackBufferFull); 
    } 
} 


void *swap_buffers() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_lock(&theFrontkMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //do we have new data in the back buffer? 
     pthread_cond_wait(&theBackBufferFull, &theBackMutex); 

     //swap buffers 
     char* tmp; 
     tmp = theBufferAPtr; 
     theBufferAPtr = theBufferBPtr; 
     theBufferBPtr = tmp; 

     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey please get more data! 
     pthread_cond_signal(&theBackBufferRefresh); 
     //hey you can use front buffer now! 
     pthread_cond_signal(&theBufferSwapped); 

    } 
} 

int main(int argc, char *argv[]) { 
    //initial fill of the back buffer 
    pthread_cond_signal(&theBackBufferRefresh); 
    while(1) { 
     if (0 != pthread_mutex_lock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
     pthread_cond_wait(&theBufferSwapped, &theFrontMutex); 
     //use the front buffer and do stuff with it 
     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
    } 
} 
+0

우리 자신을 조작 할 수 없다면 페트리 네트 모델을 만들고 그런 식으로 확인하십시오. –

+0

나는 이것을 살펴볼 것이다. 나는 전에 페트리 네트 모델을 사용한 적이 없다. 감사. –

+0

모델을 만든 후에는 도구로 가져 와서 교착 상태를 찾을 수 있습니다. 꽤 산뜻한 재료! –

답변

2

조건 변수는 일부 (mutex 보호) 공유 데이터의 상태 변화를 알리는 데 사용됩니다. 당신은 그들 자신으로 사용할 수 없습니다. 조건을 기다리는 다른 스레드가 있기 전에 스레드가 조건을 신호로 알리는 경우 어떻게 될지 고려하십시오.

+0

아, 그렇습니다. 지금보십시오. 신호를 보내고 상태 변화를 기다릴 필요가있을 때만 신호로 사용했습니다. –

1

어떤 스레드를 만들 어디 표시되지 않습니다. 스레드를 생성한다고 가정합니다.

swap_buffers()fill_back_buffer()에는 고전적인 교착 상태 구현이 포함되어 있습니다. swap_buffers()theBackBufferFull에서 대기 중이면 theBackMutex을 잠갔습니다. 신호가 theBackBufferFull으로 설정되기 전에 fill_back_buffer()theBackMutex을 기다리고 있습니다. 따라서 theBackMutex을 릴리스 할 수 없기 때문에 theBackBufferFull은 절대로 신호를 보내지 않습니다. 이것은 고전적인 교착 상태입니다.

+0

참으로 나는 전체 코드 예제를 포함하지 않았다. 그래서 2 개의 스레드가 같은 뮤텍스를 잠그려고하면 교착 상태가 발생합니까? 나는 그것이 더 똑똑하고 그것이 결국 뛰어 내릴 때까지 막을 것이라고 생각했다. –

+0

교착 상태에 대해 읽어야합니다. 동일한 뮤텍스를 잠그는 두 개의 스레드가있는 것은 아닙니다. 문제는 같은 TWO 동기화 프리미티브, 뮤텍스 및 신호에서 두 개의 스레드를 차단하고 서로 역 순서로 교착 상태가 발생한다는 것입니다. 교착 상태없이 뮤텍스를 사용할 수는 있지만, 그것은 여러분의 질문이 아닙니다. 교착 상태에 빠졌습니까? 예, 구체적으로 설명했습니다. –

+0

조건 변수가 뮤텍스를 해제한다는 것을 이해하고 있으므로, 당신이 말하는 교착 상태는 보이지 않습니다. – ninjalj

0

스와핑을 위해 추가 스레드를 사용하지 않고 수행하십시오.

+0

그래, 필 버퍼 스왑에 스와핑을 추가 할 수 있다고 가정합니다. 아마 그것은 그것을 더 간단하게 만들 것입니다. –

+0

두 개의 스레드를 갖기 위해이 작업을 수행하는 것이 일반적인 방법이지만 잠금을 올바른 순서로 수행하지 않으면 도움이되지 않습니다. –