它是一个;死锁;?在多线程中如何避免它? 我现在正在用C++ 11学习并发。 我为一门课程写了一段代码。但是,代码并没有完成运行

它是一个;死锁;?在多线程中如何避免它? 我现在正在用C++ 11学习并发。 我为一门课程写了一段代码。但是,代码并没有完成运行,c++,multithreading,c++11,concurrency,C++,Multithreading,C++11,Concurrency,我的环境: 系统:视窗10 编译器:mingw-w64x86_64-8.1.0-posix-seh-rt_v6-rev0 更新: 我认为“加入”可以结束一个线程。感谢那些评论这个问题的好心人,我明白“加入”不会“杀死”线程。它是线程执行完成时函数返回的值。另外,我的代码中的问题可能与死锁有关。我试过一些方法来解决这个问题。然而,这两者都不起作用 我所尝试的: 添加 在void Producer::prods()中函数。那不行。 后来我又编辑了一些。我添加了一个新的全局变量来检查消费者是否停止工作

我的环境:

系统:视窗10

编译器:mingw-w64x86_64-8.1.0-posix-seh-rt_v6-rev0

更新:

我认为“加入”可以结束一个线程。感谢那些评论这个问题的好心人,我明白“加入”不会“杀死”线程。它是线程执行完成时函数返回的值。另外,我的代码中的问题可能与死锁有关。我试过一些方法来解决这个问题。然而,这两者都不起作用

我所尝试的: 添加

void Producer::prods()中函数。那不行。
后来我又编辑了一些。我添加了一个新的全局变量来检查消费者是否停止工作。此外,我还添加了更多if语句来检查消费者的
voidbuffer::put()。之后,我发现代码很少工作,但大部分时间都失败了。我试着编辑这篇文章
std::this_thread::sleep_for(std::chrono::毫秒(60))单次消耗/生产操作后的睡眠时间代码。我把10毫秒放大到60毫秒。然后,代码工作得更好。现在,它很少失败

我认为代码没有完成,因为在运行过程中出现了死锁。我发现了一个可能导致Wiki死锁的原因:当一个进程或线程进入等待状态时,死锁就会发生,因为请求的系统资源被另一个等待的进程占用,而另一个等待的进程又在等待另一个等待的进程占用的资源。如果一个进程无法无限期地更改其状态,因为它请求的资源正被另一个等待的进程使用,那么系统就被称为处于死锁状态

因此,问题变成了:这真的是僵局吗?如何避免僵局?我应该编辑什么使我的代码更好

以下是新代码:

#include <iostream>
#include <thread>
#include <mutex>          // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

using namespace std;

std::mutex mu; //mutex
//std::unique_lock<mutex> locker(mu); //unique_lock
std::condition_variable cond;

std::mutex m_mutex;

int consumerRunTurns = 0;

class Buffer {
public:
Buffer():count(0) {}
void put();
int get();
bool isBufferEmpty();
bool isBufferFull();
private:
int count;
}; //end class Buffer

//Thread Class and Functions inside:
class Consumer{
public:
    Consumer(Buffer* cbptr);
    void cons();
    bool isConsumerDead();
private:
    Buffer* BufferPtr;
};

class Producer{
public:
    Producer(Buffer* pbptr, Consumer* coptr);
    void prods();
private:
    Buffer* BufferPtr;
    Consumer* ConsumerPtr;
};

int main(){
    Buffer* tc = new Buffer();
    Consumer* cdtc = new Consumer(tc);
    Producer* pdtc = new Producer(tc,cdtc);
    std::thread t[5]; //declare an array of thread objects
    int i = 0;
    for(; i<3; ++i){
        t[i]=std::thread(&Producer::prods,std::ref(pdtc));
    }
    for(; i<5; ++i){
        t[i]=std::thread(&Consumer::cons,std::ref(cdtc));
    }

    cout << "Debug1" << endl;
    cout << "Debug1" << endl;
    cout << "Debug1" << endl;

    for(i = 0; i<5; ++i){
        t[i].join();
        cout << "now i is :" << i << endl;
    }

    cout << "All threads terminated" << endl;
    return 0;
}

void Buffer::put(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    if(consumerRunTurns>=200){
            cond.notify_one();
            return;
            }
    while(isBufferFull()==1){
        if(consumerRunTurns>=200){
            cond.notify_one();
            break;
        }
        cond.wait(locker);
    }
    if(consumerRunTurns>=200){
            return;
    }
    if(isBufferFull()==0)
        cond.notify_one();
    ++count;
    std::cout << "producer thread" << this_thread::get_id() << ",count = " << count << endl;
}
int Buffer::get(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    while(isBufferEmpty()==1){
        cond.wait(locker);
    }
    if(isBufferEmpty()==0)
        cond.notify_one();
    --count;
    std::cout << "consumer thread" << this_thread::get_id() << ",count = " << count << endl;
    return count;
}
bool Buffer::isBufferEmpty(){
    if(count <=0){
        std::cout << "buffer is empty, consumer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}
bool Buffer::isBufferFull(){
    if(count >=10){
        std::cout << "buffer is full, producer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}

Consumer::Consumer(Buffer* cbptr):BufferPtr(cbptr){
}

bool Consumer::isConsumerDead(){
    if(consumerRunTurns >= 200){
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        return 1;
    }
    else
        return 0;
}

void Consumer::cons(){
    for(int i = 0; i<100; ++i){
        BufferPtr->get();
        std::this_thread::sleep_for(std::chrono::milliseconds(60));
    }
    consumerRunTurns+=100;
}

Producer::Producer(Buffer* pbptr, Consumer* coptr):BufferPtr(pbptr), ConsumerPtr(coptr){}

void Producer::prods(){
    for(int i = 0; i<100; ++i){
        if(ConsumerPtr->isConsumerDead()){
            break;
        }
        BufferPtr->put();
        std::this_thread::sleep_for(std::chrono::milliseconds(60));
    }
}
等(由于字数限制)

首先,它不会杀死线程,而是等待线程完成

您有3个生产者线程(每个线程产生100个项目),但只有2个消费者线程(每个线程消耗100个项目)。这意味着有100件剩余产品正在生产。再加上一个容量只有10项的缓冲区,你的制作人永远不会在消费者完成之前自己完成

这意味着您需要一种机制来提前结束生产者循环(即消费者循环结束后)

然而,您试图解决这个问题时,会遇到一个无限阻塞的线程(类似于死锁,但并不完全如此)。我突然想到的场景(这并不意味着这是唯一的一个),是当一个或多个生产者线程在
cond.wait(locker)上被阻塞时
(在
Buffer::put
中),但所有使用者线程都已结束(意味着
Buffer::get
中的
cond.notify_one();
将不再发生)。因此,这些生产者线程将永远等待,而相应的
连接将不会返回

为了避免这种情况,您可以考虑使用而不是<代码> STD::条件:变量::等待< /代码>,以避免阻塞等待。每次超时发生时,您都有机会检查使用者是否已结束,并在这种情况下结束生产者线程

检查使用者线程是否已结束的方法也可以改进。一个选项是首先
连接
两个使用者线程。当两个使用者线程都加入时,向所有生产者线程发出信号,表示它们也应该结束,然后
加入生产者线程。所讨论的信号可能是在生产者的每次迭代中检查的信号。如果
BufferPtr->put()更改为
BufferPtr->try_put(),它可以在缓冲区中插入项目,也可以在缓冲区已满时立即返回(或者在超时后返回,如果您愿意)


请注意,您的代码中还有更多问题(其中最重要的问题是使用相同的
condition\u变量
来表示“notempty”和“notfull”),但它们不在这个问题的范围之内。

不会终止线程-它会等待线程完成。如前所述,join将使父线程屈服,直到子线程完成执行,这可能意味着“永远”是子线程卡在循环中。据我所知,子线程根本不会立即停止:要么分离它们并确保它们在作用域结束之前退出,要么以确保它们最终退出的方式对它们进行编码。如果在
BufferPtr->put()上阻止了一个或多个生产者,会发生什么(特别是等待条件),但您的消费者都结束了?一个词:死锁。@Malboroman在谈到多线程代码时,“屈服”通常有一个特定的含义。更合适的说法是
t.join()
在线程
t
终止之前阻止调用方。典型的
yield()
函数;不执行任何操作、不等待任何操作、不花费任何时间,除非其他线程可以运行,但不实际运行。请注意,您正在生成300个项目,但只消耗200个(并且只能缓冲10个),这基本上就是您出现此问题的原因。一个简单的解决方法是,不要将消费者限制为每个只有100个项目,而是让他们一直运行,直到有项目要消费(即,直到生产者结束,缓冲区为空)。这不是死锁。死锁是一个循环锁链。这只是一个未释放的锁。@user207421:从技术上说,你是对的。在我看来,把它看作死锁并没有什么坏处,因为你有一个线程被阻塞了,而没有机会被解锁(如果它像鸭子一样嘎嘎作响…)。无论如何,为了避免混淆,我更改了术语。谢谢你指出这一点。
#include <iostream>
#include <thread>
#include <mutex>          // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

using namespace std;

std::mutex mu; //mutex
//std::unique_lock<mutex> locker(mu); //unique_lock
std::condition_variable cond;

std::mutex m_mutex;

int consumerRunTurns = 0;

class Buffer {
public:
Buffer():count(0) {}
void put();
int get();
bool isBufferEmpty();
bool isBufferFull();
private:
int count;
}; //end class Buffer

//Thread Class and Functions inside:
class Consumer{
public:
    Consumer(Buffer* cbptr);
    void cons();
    bool isConsumerDead();
private:
    Buffer* BufferPtr;
};

class Producer{
public:
    Producer(Buffer* pbptr, Consumer* coptr);
    void prods();
private:
    Buffer* BufferPtr;
    Consumer* ConsumerPtr;
};

int main(){
    Buffer* tc = new Buffer();
    Consumer* cdtc = new Consumer(tc);
    Producer* pdtc = new Producer(tc,cdtc);
    std::thread t[5]; //declare an array of thread objects
    int i = 0;
    for(; i<3; ++i){
        t[i]=std::thread(&Producer::prods,std::ref(pdtc));
    }
    for(; i<5; ++i){
        t[i]=std::thread(&Consumer::cons,std::ref(cdtc));
    }

    cout << "Debug1" << endl;
    cout << "Debug1" << endl;
    cout << "Debug1" << endl;

    for(i = 0; i<5; ++i){
        t[i].join();
        cout << "now i is :" << i << endl;
    }

    cout << "All threads terminated" << endl;
    return 0;
}

void Buffer::put(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    if(consumerRunTurns>=200){
            cond.notify_one();
            return;
            }
    while(isBufferFull()==1){
        if(consumerRunTurns>=200){
            cond.notify_one();
            break;
        }
        cond.wait(locker);
    }
    if(consumerRunTurns>=200){
            return;
    }
    if(isBufferFull()==0)
        cond.notify_one();
    ++count;
    std::cout << "producer thread" << this_thread::get_id() << ",count = " << count << endl;
}
int Buffer::get(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    while(isBufferEmpty()==1){
        cond.wait(locker);
    }
    if(isBufferEmpty()==0)
        cond.notify_one();
    --count;
    std::cout << "consumer thread" << this_thread::get_id() << ",count = " << count << endl;
    return count;
}
bool Buffer::isBufferEmpty(){
    if(count <=0){
        std::cout << "buffer is empty, consumer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}
bool Buffer::isBufferFull(){
    if(count >=10){
        std::cout << "buffer is full, producer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}

Consumer::Consumer(Buffer* cbptr):BufferPtr(cbptr){
}

bool Consumer::isConsumerDead(){
    if(consumerRunTurns >= 200){
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        return 1;
    }
    else
        return 0;
}

void Consumer::cons(){
    for(int i = 0; i<100; ++i){
        BufferPtr->get();
        std::this_thread::sleep_for(std::chrono::milliseconds(60));
    }
    consumerRunTurns+=100;
}

Producer::Producer(Buffer* pbptr, Consumer* coptr):BufferPtr(pbptr), ConsumerPtr(coptr){}

void Producer::prods(){
    for(int i = 0; i<100; ++i){
        if(ConsumerPtr->isConsumerDead()){
            break;
        }
        BufferPtr->put();
        std::this_thread::sleep_for(std::chrono::milliseconds(60));
    }
}
#include <iostream>
#include <thread>
#include <mutex>          // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

using namespace std;

std::mutex mu; //mutex
//std::unique_lock<mutex> locker(mu); //unique_lock
std::condition_variable cond;

std::mutex m_mutex;

class Buffer {
public:
Buffer():count(0) {}
void put();
int get();
bool isBufferEmpty();
bool isBufferFull();
private:
int count;
}; //end class Buffer

//Thread Class and Functions inside:
class Consumer{
public:
    Consumer(Buffer* cbptr);
    void cons();
    bool isConsumerDead();
private:
    Buffer* BufferPtr;
    int consumerDeadFlag;
};

class Producer{
public:
    Producer(Buffer* pbptr, Consumer* coptr);
    void prods();
private:
    Buffer* BufferPtr;
    Consumer* ConsumerPtr;
};

int main(){
    Buffer* tc = new Buffer();
    Consumer* cdtc = new Consumer(tc);
    Producer* pdtc = new Producer(tc,cdtc);
    std::thread t[5]; //declare an array of thread objects
    int i = 0;
    for(; i<3; ++i){
        t[i]=std::thread(&Producer::prods,std::ref(pdtc));
    }
    for(; i<5; ++i){
        t[i]=std::thread(&Consumer::cons,std::ref(cdtc));
    }

    cout << "Debug1" << endl;
    cout << "Debug1" << endl;
    cout << "Debug1" << endl;

    for(i = 0; i<5; ++i){
        t[i].join();
        cout << "now i is :" << i << endl;
    }

    cout << "All threads terminated" << endl;
    return 0;
}

void Buffer::put(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    while(isBufferFull()==1){
        cond.wait(locker);
    }
    if(isBufferFull()==0)
        cond.notify_one();
    ++count;
    std::cout << "producer thread" << this_thread::get_id() << ",count = " << count << endl;
}
int Buffer::get(){
    std::unique_lock<mutex> locker(mu); //unique_lock
    while(isBufferEmpty()==1){
        cond.wait(locker);
    }
    if(isBufferEmpty()==0)
        cond.notify_one();
    --count;
    std::cout << "consumer thread" << this_thread::get_id() << ",count = " << count << endl;
    return count;
}
bool Buffer::isBufferEmpty(){
    if(count <=0){
        std::cout << "buffer is empty, consumer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}
bool Buffer::isBufferFull(){
    if(count >=10){
        std::cout << "buffer is full, producer thread" << this_thread::get_id() << " is about to suspend." << endl;
        return 1;
    }
    else
        return 0;
}

Consumer::Consumer(Buffer* cbptr):BufferPtr(cbptr){
    consumerDeadFlag = 0;
}

bool Consumer::isConsumerDead(){
    if(consumerDeadFlag > 1){
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        cout << "consumer Dead" << endl;
        return 1;
    }
    else
        return 0;
}

void Consumer::cons(){
    for(int i = 0; i<100; ++i){
        BufferPtr->get();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    ++consumerDeadFlag;
}

Producer::Producer(Buffer* pbptr, Consumer* coptr):BufferPtr(pbptr), ConsumerPtr(coptr){}

void Producer::prods(){
    for(int i = 0; i<100; ++i){
        if(ConsumerPtr->isConsumerDead()){
            break;
        }
        BufferPtr->put();
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
producer threadDebug12,count = 1
producer thread4,count = 2

producer thread3,count = 3
Debug1
Debug1
consumer thread5,count = 2
consumer thread6,count = 1
producer thread2,count = 2
consumer thread5,count = 1
producer thread4,count = 2
producer thread3,count = 3
consumer thread6,count = 2
producer thread2,count = 3
producer thread4,count = 4
producer thread3,count = 5
consumer thread5,count = 4
consumer thread6,count = 3
producer thread2,count = 4
producer thread4,count = 5
consumer thread5,count = 4
producer thread3,count = 5
consumer thread6,count = 4
producer thread2,count = 5
consumer thread5,count = 4
producer thread4,count = 5
producer thread3,count = 6
consumer thread6,count = 5
producer thread2,count = 6
producer thread4,count = 7
producer thread3,count = 8
consumer thread5,count = 7
consumer thread6,count = 6
producer thread2,count = 7
consumer thread5,count = 6
producer thread4,count = 7
producer thread3,count = 8
consumer thread6,count = 7
producer thread2,count = 8
consumer thread5,count = 7
producer thread4,count = 8
producer thread3,count = 9
consumer thread6,count = 8
producer thread2,count = 9
producer thread4,count = 10
consumer thread5,count = 9
producer thread3,count = 10
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
buffer is full, producer thread4 is about to suspend.
consumer thread5,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer thread6,count = 9
producer thread4,count = 10
buffer is full, producer thread2 is about to suspend.
consumer thread5,count = 9
producer thread2,count = 10
buffer is full, producer thread3 is about to suspend.
consumer thread6,count = 9
producer thread3,count = 10
buffer is full, producer thread4 is about to suspend.
buffer is full, producer thread2 is about to suspend.
consumer Dead
consumer Dead
consumer Dead