2014-07-14 4 views
0

QMutex 개체, 생성자 스레드의 경우 QWaitCondition 개체 및 소비자 스레드의 경우 QWaitCondition 개체를 사용하여 스레드 안전 차단 대기열을 구현했습니다. 다음과 같이 기능 enqueue()dequeue()가 표시됩니다 :이 공유 큐가 MyQueue 객체에 대한 참조를 사용하는 생성자를 가지고 접근 할 필요가응용 프로그램을 종료 할 때 무기한으로 기다리는 제작자와 소비자

void MyQueue::enqueue(const QString& s) 
{ 
    _mutex.lock(); 

    while (_queue.size() == _maxSize) { _producer.wait(&_mutex); } 

    _queue.enqueue(s); 
    _consumer.wakeAll(); 

    _mutex.unlock(); 
} 

QString MyQueue::dequeue() 
{ 
    QString s; 

    _mutex.lock(); 

    while (_queue.empty()) { _consumer.wait(&_mutex); } 

    s = _queue.dequeue(); 

    _producer.wakeAll(); 
    _mutex.unlock(); 

    return s; 
} 

소비자 및 생산자 스레드. 이 소비자 큐가 비어 있고 소비자가 dequeue() 기능을 호출 한

  1. 경우 : 위의 구현은 제대로 작동하지만 메인 프로그램이 종료해야하는 경우 일부 소비자 또는 생산자 특히, 무기한 대기하고 있기 때문에 문제가 발생 무기한으로 기다릴 것이다.
  2. 대기열이 가득 차서 생산자가 enqueue() 함수를 호출 한 경우이 생성자는 무기한 대기합니다.

어떻게하면이 문제를 해결할 수 있습니까?

+0

셧다운을 나타내는 상태가 있고 소비자 또는 생산자를 깨운 후 읽습니다. 대기열이 비어 있고 모든 소비자가 멈출 때까지 모든 생산자가 모든 소비자를 깨우지 못하게합니다. –

답변

1

원자 플래그 (std::atomic_bool 또는 QAtomicInt을 사용할 수 있음)를 사용하고 있고 _consumer.wait이 시간 초과를 사용하는 것이 가장 간단한 방법이라고 생각합니다. cancel==true가 다시 기다려야 그렇지 않으면 종료하면

당신 detect a timeout ( wait 반환 false 타임 아웃이 발생한 경우)

는 플래그를 확인합니다. 따라서 최악의 경우에는 time 밀리 초를 기다린 다음 종료됩니다. 종료가 유일한 문제라면

0

, 당신은 while 루프에서 확인할 또 다른 조건을 추가하여이 문제를 해결 할 수 있습니다

while (_queue.size() == _maxSize) { 
     _producer.wait(&_mutex); 
     if (_queue.shutting_down()) return; 
    } 

큐가 종료 플래그를 설정합니다 API를 통해 확장 될 수 계속 대기중인 스레드를 깨우십시오.

0

가장 간단한 방법은 true으로 설정 한 글로벌 부울 (exit_now 또는 그 밖)을 제공 한 다음 두 조건 변수로 브로드 캐스트하여 깨우기 (wake up)하는 것입니다. 그들은 깨어나서 부울을 확인하고 스레드를 종료합니다.