Linux之线程进阶(二)
封装一下条件变量封装锁重谈生产消费模型任何时刻只有一个线程再访问阻塞队列???他的高效性又该怎么理解呢??获取任务队列和处理任务数据是可以并发的因为我们将阻塞队列当作一个整体来进行使用,也就是将临界资源被我们当作一个人完整的资源,要么不用,要么必须全部使用POSIX信号量信号量信号量本身是一个计数器,是对资源的预定机制,对其进行原子性的,--前提:临界资源是多份的,可以多个执行流访问如果资源只有一份---二元信号量---mutex等同于二元信号量sem_init参数解析sem_t *sem信号量变量的地址要初始化的信号量对象。int pshared重点考点0信号量用于同一个进程内的多个线程共享绝大多数场景我们写线程代码都填 0非 0信号量放在共享内存用于多个进程之间共享unsigned int value信号量的初始资源计数value 1二元信号量等价互斥锁保护临界资源同一时刻只允许一个执行流访问value 1计数信号量控制最多 N 个线程同时访问资源限流返回值返回0初始化成功返回-1失败全局变量errno保存错误码sem_destroy参数说明*sem_tsem含义指向匿名信号量的指针信号量变量地址要求该信号量必须提前使用sem_init完成初始化不能传入sem_open创建的有名信号量调用时不能有任何线程正在阻塞等待该信号量sem_wait返回值返回类型int返回 0信号量销毁成功返回 -1销毁失败全局变量errno存放具体错误编号等所有线程执行完、不再操作这个信号量之后传入信号量地址调用 sem_destroy (sem);sem_waitP 操作申请资源如果信号量值 0信号量value - 1函数直接返回线程继续运行如果信号量值 0线程阻塞休眠直到其他线程调用sem_post释放资源唤醒自己参数说明sem_t *sem信号量对象地址匿名 / 有名信号量都可以使用返回值0成功获取资源-1调用失败errno保存错误码sem_postV 操作释放资源将信号量的值value 1如果此时有线程阻塞在sem_wait等待该信号量会唤醒其中一个阻塞线程常搭配 sem_wait 成对使用sem_wait 占资源sem_post 归还资源参数说明sem_t *sem信号量对象地址匿名信号量、有名信号量均可传入要求信号量已经完成初始化。返回值0执行成功-1调用失败全局变量errno保存错误码新的cp问题环形缓冲区环形队列中head tail同时代表两种状态队列为空 或 队列已满无法直接区分主流两种解决办法方案 1增设计数器额外定义一个size计数器记录当前队列有效元素个数size 0→ 队列空head tailsize 容量max→ 队列满head tail优点数组空间全部可用不浪费存储空间缺点多维护一个变量多线程场景下要额外保证计数器线程安全方案 2牺牲一个存储位置不新增变量故意留一个空位不用用来区分空和满head tail队列为空(tail 1) % max head队列已满优点不需要额外变量实现简单缺点数组有一格空间永久无法存放数据浪费一个位置将环形队列看成一个大圆盘,然后tail放苹果,head拿苹果规则为空:tail放苹果,head拿苹果为满:head放苹果非空也非满:生产者和消费者指向不同的位置,并发生产和消费,并且生产者不能套圈消费者不能超过生产者封装信号量