2013-12-07 4 views
1

Класс Thread.h реализует метод запуска, такой как класс Thread в Java, поэтому выполняется каждый класс, наследующий реализацию Thread.C++ 11 thread wait

В примере ниже выполните два потока: Продюсер и считыватель сначала (Производитель) распечатывают счетчик в бесконечном цикле, второй поток (Reader) 1) ожидают вызов на Produce, 2) напишут некоторые int и 3) weakup Produce with уведомлять метод. Wait использует переменную condition_variable.

Проблема «производитель-> wait();» внутри метода Reader :: run не блокирует производителя, и он продолжает писать, что не так?

компилировать с

g++ -std=c++11 -pthread main.cpp 

заранее спасибо

//in main.cpp 
int main() { 
    Producer p ; 
    Reader r (&p); 
    p.start(); 
    r.start(); 
    p.join(); 
    r.join(); 
    cout << "end" << endl << flush; 
} 

классы:

// in main.cpp 
#include <iostream> 
#include <unistd.h> 
#include "Thread.h" 
class Producer : public Thread { 
public: 
    Producer() {i = 0;} 

    virtual void run() ; 
private: 
    int i; 
}; 
void Producer::run() { 
    while (1) { 
     usleep (1000); 
     cout << "Producer count: " << i++ << endl << flush; 
    }; 
}; 

класс читатель

// in main.cpp 
class Reader : public Thread { 
public: 
    Reader (Producer* p) {producer = p; i = 0;} 

virtual void run() ; 
private: 
    int i; 
    Producer* producer; 
}; 
void Reader::run() { 
    while (1) { 
     usleep (1000); 
     i++; 
     if (! (i % 1000)) { 
      cout << "waiting Producer" << endl << flush; 
      producer->wait(); 
      cout << "write 10000 int" << endl << flush; 
      for (int k = 0; k < 1000; k++) { 
       usleep (1000); 
       cout << "      Reader: count " << k << endl << flush; 
      } 

      producer->notify(); 
     } 
    }; 
}; 

Thread.h:

#ifndef THREAD_H_ 
#define THREAD_H_ 
#include <thread> 
#include <mutex> 
#include <condition_variable> 
using namespace std; 

class Runnable { 
public: 
    virtual void run() = 0; 
}; 

class Thread: virtual public Runnable { 
private: 
    mutex mtx; 
    condition_variable cv; 
    thread* theThread; 
    Runnable * _runnable; 
    Runnable * execRunnable; 

    static void * __run (void * cthis) { 
     static_cast<Runnable*> (cthis)->run(); 
     return nullptr; 
    } 

public: 
    Thread() : 
     _runnable (nullptr) { 
     theThread = nullptr; 
     execRunnable = this; 
    } 

    virtual ~Thread() { 
     if (theThread) { 
      theThread->detach(); 
      delete theThread; 
      theThread = nullptr; 
     } 
    } 

void wait () { 
    unique_lock<std::mutex> lk (mtx); 
    cv.wait (lk); 
} 

void notify() { 
    cv.notify_all(); 
} 

void start() { 
    if (this->_runnable != nullptr) { 
     execRunnable = this->_runnable; 
    } 

    if (theThread) { 
     delete theThread; 
    } 

    theThread = new thread (__run, execRunnable); 
} 

void join() { 
    if (theThread) { 
     theThread->join(); 
     delete theThread; 
     theThread = nullptr; 
    } 
} 

bool isJoinable() { 
    return theThread->joinable(); 
} 

void stop() { 
    if (theThread) { 
     theThread->detach(); 
     delete theThread; 
     theThread = nullptr; 
    } 
} 

}; 
#endif 

ответ

1

Вы не можете остановить продюсерский нить так же, как это. Вам нужно установить некоторую переменную из вашего потока читателя и проверить ее значение внутри производителя. Затем продюсер может вызвать wait() и будет продолжаться только после того, как читатель вызвал notify(). BTW. endl также делает flush, нет необходимости называть его снова.