1.sem信号量类
(1)信号量类与互斥锁的区别:
-锁是服务于共享资源的,而semaphore是服务于多个线程间的执行的逻辑顺序的。比如线程A,线程B,线程C等于线程A加B,那么必须A、B执行完,线程C才能执行,那么这时候我们就需要sem来调度线程。
-互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区。
信号量总结:
//信号量类型
sem_t sem;
//初始化信号量
sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
pshared:0 - 线程同步;1 - 进程同步。
value:最多有几个线程操作共享数据
//销毁信号量
sem_destroy(sem_t *sem);
//加锁
sem_wait(sem_t *sem);
调用一次相当于对sem做了--操作
如果sem值为0, 线程会阻塞
//尝试加锁
sem_trywait(sem_t *sem);
sem == 0, 加锁失败, 不阻塞, 直接返回
//解锁
sem_post(sem_t *sem);
对sem做了++操作
线程池采用预创建的技术,在应用程序启动之后,将立即创建一定数量的线程(N1),放入空闲队列中。这些线程都是处于阻塞(Suspended)状态,不消耗CPU,但占用较小的内存空间。当任务到来后,缓冲池选择一个空闲线程,把任务传入此线程中运行。当N1个线程都在处理任务后,缓冲池自动创建一定数量的新线程,用于处理更多的任务。在任务执行完毕后线程也不退出,而是继续保持在池中等待下一次的任务。当系统比较空闲时,大部分线程都一直处于暂停状态,线程池自动销毁一部分线程,回收系统资源。
构建线程池框架
一般线程池都必须具备下面几个组成部分:
- 线程池管理器:用于创建并管理线程池
- 工作线程: 线程池中实际执行的线程
- 任务接口: 尽管线程池大多数情况下是用来支持网络服务器,但是我们将线程执行的任务抽象出来,形成任务接口,从而是的线程池与具体的任务无关。
- 任务队列: 线程池的概念具体到实现则可能是队列,链表之类的数据结构,其中保存执行线程。
并发下线程池的最佳数量
如果是CPU密集型应用,则线程池大小设置为N+1;(对于计算密集型的任务,在拥有N个处理器的系统上,当线程池的大小为N+1时,通常能实现最优的效率)
如果是IO密集型应用,则线程池大小设置为2N+1;IO密集型任务可以使用稍大的线程池,一般为2*CPU核心数。IO密集型任务CPU使用率并不高,因此可以让CPU在等待IO的时候去处理别的任务,充分利用CPU时间。
(2条消息) 深入解析C++编程中线程池的使用_歌行梅村的专栏-CSDN博客_c++ 线程池