生産者と消費者の問題(C++実現)


コードの概要
  • TはT個の生産者がいることを示している.同時にT人の消費者もいる.そして各生産者は合計T個のデータを生産する.消費者1人当たり合計T個のデータを消費する.
  • Nは最大乱数の大きい値
  • を表す.
  • その信号量の実現、私は直接copyの授業の上でです.

  • コード#コード#
    バージョン1
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    class Semaphore {
    public:
        Semaphore(long count = 0) :count_(count) {}
        void Signal() {
            unique_lock lock(mutex_);
            ++count_;
            cv_.notify_one();
        }
        void Wait() {
            unique_lock lock(mutex_);
            //      false     ,
            //   Lambda         
            cv_.wait(lock, [=] { return count_ > 0; });
            --count_;
        }
        void setCount(long count = 0) {
            count_ = count;
        }
    private:
        mutex mutex_;
        condition_variable cv_;
        long count_;
    };
    
    
    int T, N;
    int BufferSize;
    queue<string> output;
    queue<int> Buffer;
    Semaphore BufferChoose, BufferCnt, BufferLast;
    
    void Poducer(int cnt) {
        srand(time(NULL));
        int data;
        for (int i = 0; i < T; ++i) {
            BufferLast.Wait();
            BufferChoose.Wait();
            data = rand() % N;
            Buffer.push(data);
            string temp = string("   ") + to_string(cnt) + string("       ") + to_string(data);
            output.push(temp);
            BufferChoose.Signal();
            BufferCnt.Signal();
        }
    }
    
    void Consumer(int cnt) {
        int data;
        for (int i = 0; i < T; ++i) {
            BufferCnt.Wait();
            BufferChoose.Wait();
            data = Buffer.front();
            Buffer.pop();
            string temp = string("   ") + to_string(cnt) + string("       ") + to_string(data) + string(",   ") + to_string(data * data);
            output.push(temp);
            BufferChoose.Signal();
            BufferLast.Signal();
        }
    }
    
    int main() {
        T = 4;
        N = 100;
        BufferSize = 2;
        _ASSERT(BufferSize > 0);
    
        BufferChoose.setCount(1);
        BufferCnt.setCount(0);
        BufferLast.setCount(BufferSize);
    
        vector vt;
        for (int i = 0; i < 2*T; ++i) {
            if (i < T) vt.push_back(thread(Poducer, i));
            else vt.push_back(thread(Consumer, i-T));
        }
        for (int i = 0; i < 2*T; ++i) {
            vt[i].join();
        }
        while (!output.empty()) {
            cout << output.front() << endl;
            output.pop();
        }
        system("pause");
    }

    バージョン2
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    class Semaphore {
    public:
        Semaphore(long count = 0) :count_(count) {}
        void Signal() {
            unique_lock lock(mutex_);
            ++count_;
            cv_.notify_one();
        }
        void Wait() {
            unique_lock lock(mutex_);
            //      false     ,
            //   Lambda         
            cv_.wait(lock, [=] { return count_ > 0; });
            --count_;
        }
        void setCount(long count = 0) {
            count_ = count;
        }
    private:
        mutex mutex_;
        condition_variable cv_;
        long count_;
    };
    
    
    int T, N;
    int BufferSize;
    queue<string> output;
    queue<int> Buffer;
    Semaphore BufferChoose, BufferCnt, BufferLast;
    
    void Poducer(int cnt) {
        srand(time(NULL)+cnt);
        int data;
        for (int i = 0; i < T; ++i) {
            BufferLast.Wait();
            BufferChoose.Wait();
            data = rand() % N;
            Buffer.push(data);
            string temp = string("   ") + to_string(cnt) + string("       ") + to_string(data);
            output.push(temp);
            BufferChoose.Signal();
            BufferCnt.Signal();
        }
    }
    
    void Consumer(int cnt) {
        int data;
        for (int i = 0; i < T; ++i) {
            BufferCnt.Wait();
            BufferChoose.Wait();
            data = Buffer.front();
            Buffer.pop();
            string temp = string("   ") + to_string(cnt) + string("       ") + to_string(data) + string(",   ") + to_string(data * data);
            output.push(temp);
            BufferChoose.Signal();
            BufferLast.Signal();
        }
    }
    
    int main() {
        T = 4;
        N = 100;
        BufferSize = 10;
        _ASSERT(BufferSize > 0);
    
        BufferChoose.setCount(1);
        BufferCnt.setCount(0);
        BufferLast.setCount(BufferSize);
    
        vector vt;
        for (int i = 0; i < 2*T; ++i) {
            if (i < T) vt.push_back(thread(Poducer, i));
            else vt.push_back(thread(Consumer, i-T));
        }
        for (int i = 0; i < 2*T; ++i) {
            vt[i].join();
        }
        while (!output.empty()) {
            cout << output.front() << endl;
            output.pop();
        }
        system("pause");
    }