9.多线程与fork()
永远不要在多线程程序里面调用fork。
Linux的fork函数, 会复制一个进程, 对于多线程程序而言, fork函数复制的是用fork的那个线程, 而并不复制其他的线程。 fork之后其他线程都不见了。 Linux存在forkall语义的系统调用, 无法做到将多线程全部复制。
多线程程序在fork之前, 其他线程可能正持有互斥量处理临界区的代码。 fork之后, 其他线程都不见了, 那么互斥量的值可能处于不可用的状态, 也不会有其他线程来将互斥量解锁。
10.生产者与消费者模型
10.1生产者与消费者模型的本质
本质上是一个线程安全的队列,和两种角色的线程(生产者和消费者)
存在三种关系:
1、生产者与生产者互斥
2、消费者与消费者互斥
3、生产者与消费者同步+互斥
10.2为什么需要生产者与消费者模型?
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生成完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列中取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费解耦的。
10.3优点
1、解耦
2、支持高并发
3、支持忙闲不均
10.4实现两个消费者线程,两个生产者线程的生产者消费者模型
生产者生成时用的同一个全局变量,故对该全局变量进行了加锁。
#include #include #include #include #include #include #define PTHREAD_COUNT 2int data = 0;//全局变量作为插入数据pthread_mutex_t mutex1;class ModelOfConProd{ public: ModelOfConProd()//构造 { _capacity = 10; pthread_mutex_init(&_mutex,NULL); pthread_cond_init(&_cons,NULL); pthread_cond_init(&_prod,NULL); } ~ModelOfConProd()//析构 { _capacity = 0; pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cons); pthread_cond_destroy(&_prod); } void Push(int data)//push数据,生产者线程使用的 { pthread_mutex_lock(&_mutex); while((int)_queue.size() >= _capacity) { pthread_cond_wait(&_prod,&_mutex); } _queue.push(data); pthread_mutex_unlock(&_mutex); pthread_cond_signal(&_cons); } void Pop(int& data)//pop数据,消费者线程使用的 { pthread_mutex_lock(&_mutex); while(_queue.empty()) { pthread_cond_wait(&_cons,&_mutex); } data = _queue.front(); _queue.pop(); pthread_mutex_unlock(&_mutex); pthread_cond_signal(&_prod); } private: int _capacity;//容量大小,限制容量大小 std::queue _queue;//队列 pthread_mutex_t _mutex;//互斥锁 pthread_cond_t _cons;//消费者条件变量 pthread_cond_t _prod;//生产者条件变量};void *ConsumerStart(void *arg)//消费者入口函数{ ModelOfConProd *cp = (ModelOfConProd *)arg; while(1) { cp->Push(data); printf("i am pid : %d,i push :%dn",(int)syscall(SYS_gettid),data); pthread_mutex_lock(&mutex1);//++的时候,给该全局变量加锁 ++data; pthread_mutex_unlock(&mutex1); }}void *ProductsStart(void *arg)//生产者入口函数{ ModelOfConProd *cp = (ModelOfConProd *)arg; int data = 0; while(1) { cp->Pop(data); printf("i am pid : %d,i pop :%dn",(int)syscall(SYS_gettid),data); }}int main(){ ModelOfConProd *cp = new ModelOfConProd; pthread_mutex_init(&mutex1,NULL); pthread_t cons[PTHREAD_COUNT],prod[PTHREAD_COUNT]; for(int i = 0;i < PTHREAD_COUNT; ++i) { int ret = pthread_create(&cons[i],NULL,ConsumerStart,(void*)cp); if(ret < 0) { perror("pthread_create"); return -1; } ret = pthread_create(&prod[i],NULL,ProductsStart,(void*)cp); if(ret < 0) { perror("pthread_create"); return -1; } } for(int i = 0;i < PTHREAD_COUNT;++i) { pthread_join(cons[i],NULL); pthread_join(prod[i],NULL); } pthread_mutex_destroy(&mutex1); return 0;}