【Linux】多线程编程 |
您所在的位置:网站首页 › linux信号量 › 【Linux】多线程编程 |
目录 一.线程同步 1.什么是线程同步 2.为什么需要线程同步 3.如何实现线程同步 二.条件变量 1.常见接口以及使用 2.wiat/signal中的第二个参数mutex的意义 3.代码验证 三.POSIX信号量 1.概念 2.常见接口以及使用 四.条件变量vsPOSIX信号量 一.线程同步 1.什么是线程同步同步: 在保证数据安全的情况下, 让线程能按照某种特定顺序访问临界资源, 从而有效避免饥饿问题, 主要为了解决访问临界资源合理性问题 其中, 按照某种特定顺序访问临界资源, 实际上操作系统的调度队列自动帮助我们维护的, 对于我们而言是透明的, 因为如果有线程在等待资源, 那么一定是一个个的被挂起, 自然就有了顺序性 2.为什么需要线程同步情景一: 假设有某个线程竞争能力比较强, 就会导致其他线程迟迟访问不到临界资源, 造成饥饿问题 情景二: 线程在使用临界资源前必须要检测临界资源是否就绪, 检测这一过程本质上也是访问临界资源, 那么就需要互斥的访问(加锁解锁), 如果临界资源没有准备就绪, 线程就会不断地检测, 即不断地互斥访问, 也就是在不断加锁解锁, 频繁做无效的加锁解锁工作, 是一种极大的资源浪费 情景三: 生活中的例子, 当我们要去商店买东西时, 总是要问一下是否还有货, 如果没有就要改天再来, 那么我们不可能每次问的时候都在亲自跑到商店去问, 而是在第一次问的时候就留好了联系方式, 如果有货的话老板会联系我来拿, 这本质上就是资源已就绪, 老板唤醒了我这个等待中的线程, 让我来访问 3.如何实现线程同步线程同步的本质上就是: 对临界资源做检查, 如果资源不就绪就等待, 资源一但就绪就将等待中的线程唤醒, 从而高效有序的进行访问, 避免不必要的锁资源浪费以及饥饿问题 对临界资源检查, 本质也是在访问临界资源, 所以也要互斥进行(信号量不需要, 后续会解释) 如果通过编码的方式实现线程同步: 1.条件变量 2.POSIX信号量 二.条件变量本质上条件变量就是一个"等待-唤醒"的过程 1.常见接口以及使用需要包头文件 类型: pthread_cond_t 定义方式: 与pthread_mutex_t的定义方式一样 (互斥量mutex详解, 传送入口: http://t.csdn.cn/ikHAk) 定义为全局 or 定义为静态: pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 定义为局部: int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); int pthread_cond_destroy(pthread_cond_t *cond); 使用方式: 等待 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); 唤醒 int pthread_cond_broadcast(pthread_cond_t *cond); (广播, 唤醒全部正在等待线程) int pthread_cond_signal(pthread_cond_t *cond); (只唤醒一个) 2.wiat/signal中的第二个参数mutex的意义对临界资源检查, 本质也是在访问临界资源, 所以也要互斥进行 在使用上, 一定是 pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); ------------------------------------------------- 唤醒pthread_cond_signal(&cond);是否互斥进行看具体场景 在wait接口传入锁地址的意义: 如果一个持有锁的线程挂起等待了, 它是持有锁等待的, 会导致其他线程申请不到锁 所以pthread_cond_wait接口的内部实现, 是先解锁, 等到被唤醒的时候再加锁, 这样的一个设计 所以就需要传入mutex地址 3.代码验证 #include #include #include #include const static size_t THREAD_NUM = 3; typedef void (*func_t)(const std::string &, pthread_mutex_t *, pthread_cond_t *); volatile bool quit = false; struct ThreadData { ThreadData(const std::string &name, func_t func, pthread_mutex_t *mutex, pthread_cond_t *cond) : _name(name), _func(func), _mutex(mutex), _cond(cond) { } std::string _name; func_t _func; pthread_mutex_t *_mutex; pthread_cond_t *_cond; }; void func1(const std::string &info, pthread_mutex_t *mutex, pthread_cond_t *cond) { while (!quit) { pthread_mutex_lock(mutex); pthread_cond_wait(cond, mutex); if (!quit) std::cout |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |