三 Linux--多线程( 三 )


三 Linux--多线程

文章插图
生产者生产速度快,导致一上来生产者就把队列塞满了任务,接着唤醒消费者来消费,然后挂起等待 。紧接着消费者处理完一个任务就唤醒生产者来生产,生产者生产了一个任务就喊消费者来消费,然后继续挂起 。可以看出的是,在这种情况下,队列长时间是满的,生产者大部分时间是挂起等待的 。生产者和消费者开始一小部分时间内步调是不一致的,生产者生产完,消费者才消费是串行的,但是过了一会,二者步调就变得一致了,且速度是随消费者的
3.生产者慢,消费者快
三 Linux--多线程

文章插图
生产者的速度慢,生产者生产一个任务立马唤醒消费者,消费者处理完一个数据,发现队列为空,然后挂起等待,接着生产者继续生产一个任务,然后唤醒消费者 。可以看出的是,队列大部分时间是为空的,消费者大部分时间是处于挂起等待的,二者步调一直是一致的,且执行速度是随生产者的,也是并行的
多生产者和多消费者模型分析做到几点:
  • 生产者之间需要互斥,也就是生产者和生产者之间需要组内竞争一把锁,消费者也是如此
  • 生产者和消费者之间用互斥量和条件变量做到同步和互斥(上面就做到了)
#define P_COUNT 3#define C_COUNT 3BlockQueue<Task>* q;pthread_mutex_t c_lock;// 消费者的锁pthread_mutex_t p_lock;// 生产者的锁void* Consumer(void* arg){long id = (long)arg;while (1){pthread_mutex_lock(&c_lock);// 消费(取)数据Task t(0, 0);q->ConsumeData(t);cout << "consumer " << id << " consumes a task: " << t.GetA() << " + " << t.GetB() << " = " << t.Run() << endl;pthread_mutex_unlock(&c_lock);sleep(1);}}void* Productor(void* arg){long id = (long)arg;while (1){pthread_mutex_lock(&p_lock);// 生产(放)数据int x = rand()%10 + 1;int y = rand()%10 + 1;Task t(x, y);cout << "productor " << id << " produncs a task: " << x << " + " << y << " = ?" << endl;q->ProductData(t);pthread_mutex_unlock(&p_lock);sleep(1);}}int main(){srand((size_t)time(nullptr));pthread_mutex_init(&c_lock, nullptr);pthread_mutex_init(&p_lock, nullptr);// 创建一个交易场所q =new BlockQueue<Task>;pthread_t p[P_COUNT];pthread_t c[C_COUNT];for (long i = 0; i < P_COUNT; ++i){pthread_create(p+i, nullptr, Productor, (void*)(i+1));}for (long i = 0; i < C_COUNT; ++i){pthread_create(c+i, nullptr, Consumer, (void*)(i+1));}for (int i = 0; i < C_COUNT; ++i){pthread_join(c[i], nullptr);}for (int i = 0; i < P_COUNT; ++i){pthread_join(p[i], nullptr);}pthread_mutex_destroy(&c_lock);pthread_mutex_destroy(&p_lock);delete q;return 0;}注意:
  • 生产者之间需要一个互斥量,消费者之间也需要一个互斥量
  • 生产者和消费者的个数可以自己调整宏变量
运行结果如下:
三 Linux--多线程

文章插图
POSIX信号量介绍POSIX信号量: 该信号量允许进程和线程同步对共享资源的访问 。同时也可以用于实现线程间同步 。
总结几点:
  • 是什么? 信号量本质是一个计数器,描述临界资源的有效个数 。申请一个资源就对信号量减1(P操作),释放一个资源就对信号量加1(V操作)
  • 为什么? 临界资源可以看成很多份,互相不冲突且高效
  • 怎么用? 可以使用信号量的相关接口,来申请信号量和释放信号量(下面详细介绍)
相关接口的介绍下面要介绍的POSIX信号量相关接口都是在semaphore.h的头文件中 。信号量是一个类型为

经验总结扩展阅读