• 死锁4个条件:1)互斥条件 2)不可剥夺条件 3)请求和保持条件 4)循环等待条件

  • 管程 :把锁和条件变量联合起来使用。锁实现互斥,条件变量实现同步。同步是协调多个线程运行速度

  • 细度粒锁:减小一个锁所控制的共享数据量

  • 递归锁:可以反复上锁,上锁多少次就要解锁多少次锁才能变为空闲。初始化pthread_mutex_t时将锁的类型设为PTHREAD_MUTEX_RECURSIVE即可设置递归锁

自旋锁

  • test_and_set() : 测试并设置指令。硬件提供 讲某一个位置的值的读取和设置值能成为不可分割的操作
  • 只适用于已知单个线程持有锁时间很短情况,缺点是效率低
struct lock {int value;
}void lock_acquire(struct lock *my_lock) { //获得锁while (test_and_set(&my_lock->value));return ;
}void lock_unlock(struct lock *my_lock) { //解锁my_lock->value = 0;return ;
}
  • 对换自旋锁. 硬件存储于内存中两个位置的值在一个不可分割的操作中对换
int test = 1;
do {swap(&test, &lock);
} while (test);

锁实现线程间的同步

  • mutex变量是非0即1,及可用资源数量
  • 创建锁 及 销毁锁
#include <pthread.h>//销毁pthread_mutex_init创建的mutex
int pthread_mutex_destroy(pthread_mutex_t *mutex); //对mutex初始化,attr为mutex的属性
//成功返回0,失败返回errno
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t * restrict attr);//mutex变量是全局变量或static变量,可用以下宏初始化
//以下等价于pthread_mutex_init(mutex, NULL);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  • 加锁及解锁. 成功返回0 失败返回errno
#include <pthread.h>//等待获得mutex锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//不等待获得mutex锁,若mutex被其他线程用则推出等待立即返回EBUSY
int pthread_mutex_trylock(pthread_mutex_t *mutex);int pthread_mutex_unlock(pthread_mutex_t *mutex);

  • 死锁

    1)一个线程先后两次调用lock(),导致永远等待被自己占用的锁,陷入死锁

    2)两个线程分别获得了锁后,分别调用对方的锁,导致双方永远挂起状态陷入死锁


条件变量实现线程间的同步

  • 条件变量阻塞等待一个条件,或唤醒等待这个条件的线程
  • 创建条件变量 及 销毁条件变量. 成功返回0,失败返回errno
#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);//以下等价于pthread_cond_init(cond, NULL);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

  • 条件变量操作函数。成功返回0,失败返回errno
#include <pthread.h>//abstime指定的时刻仍没有线程唤醒当前进程,返回ETIMEOUT
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);//阻塞等待条件变量发生
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);
  • 条件变量实现生产者与消费者
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t headlock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t hadGoods = PTHREAD_COND_INITIALIZER;typedef struct Goods {int data;struct Goods *next;
} Goods;
Goods *head = NULL;void *producer(void *arg) { //生成者Goods *ng;while (1) {ng = (Goods *)malloc(sizeof(Goods));ng->data = rand() % 100;pthread_mutex_lock(&headlock);//头插法ng->next = head;head = ng;pthread_mutex_unlock(&headlock);pthread_cond_signal(&hadGoods);printf("producer %d\n", ng->data);sleep(rand() % 3);}
}void *consumer(void *arg) { //消费者Goods *k;while (1) {pthread_mutex_lock(&headlock);if (!head) {pthread_cond_wait(&hadGoods, &headlock);}k = head;head = head->next;pthread_mutex_unlock(&headlock);printf("consumer %d\n", k->data);free(k);sleep(rand() % 3);}
}int main() {srand(time(NULL));pthread_t pid, cid;pthread_create(&pid, NULL, producer, NULL);pthread_create(&cid, NULL, consumer, NULL);pthread_join(pid, NULL);pthread_join(cid, NULL);return 0;
}

信号量实现线程间的同步

  • 信号量可用于同一进程间的同步,也可用于不同进程间的同步

    semaphore可用资源数有多个,和mutex不同点在于可以大于1

#include <semaphore.h>//初始化sem_t变量,value-可用资源数
//pshared=0表示信号量用于同一进程的线程间同步
int sem_init(sem_t *sem, int pshared, unsigned int value);//获得资源,sem_t值减1,如果减1前值为0则挂起等待
int sem_wait(sem_t *sem); //获得资源,sem_t值减1,如果减1前值为0则不会挂起等待
int sem_trywait(sem_t *sem); //sem_t值加1,且唤醒挂起等待的线程
int sem_post(sem_t *sem); int sem_destroy(sem_t *sem); //释放信号量资源
  • 信号量实现生产者与消费者
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>int q[5];
sem_t nil_no, goods_no;void *producer(void *arg) {int i = 0;while (1) {sem_wait(&nil_no);q[i] = rand() % 100 + 1;printf("producer %d\n", q[i]);sem_post(&goods_no);i = (i + 1) % 5;sleep(rand() % 3);}
}void *consumer(void *arg) {int i = 0;while (1) {sem_wait(&goods_no);printf("consumer %d\n", q[i]);q[i] = 0;sem_post(&nil_no);i = (i + 1) % 5;sleep(rand() % 3);}
}int main() {srand(time(NULL));sem_init(&nil_no, 0, 5);sem_init(&goods_no, 0, 0);//macOS//sem_open("nil_no", O_CREAT|O_EXCL, S_IRWXU, 5);//sem_open("goods_no", O_CREAT|O_EXCL, S_IRWXU, 0);pthread_t pid, cid;pthread_create(&pid, NULL, producer, NULL);pthread_create(&cid, NULL, consumer, NULL);pthread_join(pid, NULL);pthread_join(cid, NULL);return 0;
}

LinuxC:锁、条件变量、信号量实现线程间的同步 生产者与消费者 pthread_mutex_init pthread_cond_init sem_init相关推荐

  1. Python | threading03 - 使用条件对象,实现线程间的同步

    文章目录 一.前言 二.生产者-消费者的模型 2.1.代码 2.2.运行 2.3.wait( )方法会将互斥锁释放 三.条件同步 - threading.Condition( ) 3.1.相关API ...

  2. 多线程-线程间通信-多生产者多消费者示例

    1.多线程-线程间通信-多生产者多消费者问题 多生产者和多消费者.等待唤醒机制. 产生了两个问题: 1.出现了多次连续生产,未消费,或者一个商品被消费多次. 解决:必须要--------每一个被唤醒的 ...

  3. 铂金04:令行禁止-为何说信号量是线程间的同步利器

    欢迎来到<并发王者课>,本文是该系列文章中的第17篇. 在并发编程中,信号量是线程同步的重要工具.在本文中,我将带你认识信号量的概念.用法.种类以及Java中的信号量. 信号量(Semap ...

  4. java多线程:线程间的通信-生产者和消费者(三)

    在一个程序中,往往会通过多个线程协同来共同完成一项任务,线程间必然需要进行信息的传递,也即是进程间的通信,我们用生产者和消费者的例子来具体分析: 对于生产者和消费者之间的关系,他们都是针对同一资源的操 ...

  5. java基础—线程间的通讯 生产者与消费者

    线程间的的通讯  生产者与消费者 public class TestDemos3 {public static void main(String[] args){Res r = new Res();I ...

  6. Linux c线程间的同步----互斥锁、条件变量、信号量

    线程 一个进程中的所有线程共享为进程分配的地址空间.所以进程地址空间中的代码段和数据段都是共享的. 如果定义一个函数在各个线程中都可以调用,定义一个全部变量,在各个线程中都可以访问到. 各线程共享资源 ...

  7. linux 条件变量函数,Linux线程同步之条件变量

    条件变量变量也是出自POSIX线程标准,另一种线程同步机制,.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量 ...

  8. 线程间通信————同步

          同步 是指多个任务按照约定的先后次序 相互配合完成一件事情 信号量: 由信号量决定 线程是继续执行 还是阻塞等待 信号量代表某种资源 其值表示系统中该资源的数量 信号量是一个受保护的量 只 ...

  9. linux线程同步互斥说法,linux线程间的同步与互斥知识点总结

    在线程并发执行的时候,我们需要保证临界资源的安全访问,防止线程争抢资源,造成数据二义性. 线程同步: 条件变量 为什么使用条件变量? 对临界资源的时序可控性,条件满足会通知其他等待操作临界资源的线程, ...

  10. 用信号量实现任务间单向同步

    文章目录 1 用信号量实现任务间单向同步 1.1 问题需求 1.2 解决方案 1.3 其它方案 1.4 典型案例 1 用信号量实现任务间单向同步 1.1 问题需求 某一任务必须等待另一任务允许后才能继 ...

最新文章

  1. Dictionary Serializer(Dictionary 序列化)
  2. 3.6 判断两个链表是否相交
  3. android studio安装中出现Failed to install Intel HAXM错误的解决方法
  4. 程序员数学基础【六、枚举 区块链,虚拟币种、币包约束,内环版本】(Java版本)
  5. android 按钮点击间隔,如何自定义android中按下的长/延迟按钮的时间间隔
  6. 手把手教你学Dapr - 6. 发布订阅
  7. 内存中数据模型和大数据持久性
  8. lisp eval apply_SICP远古魔法-LISP概览(1-2)
  9. Amazon S3数据一致性模型
  10. Openstack Python 源代码的路径
  11. layui横向时间线_用打火机或烟头烧羽毛球拍线坏处多
  12. WINCE6.0+ILI9806E驱动IC显示屏调试总结
  13. 基于51单片机+SYN6288语音播报
  14. cython编译python_cython编译报错
  15. 记录虚拟机中更改虚拟网络编辑器无效的解决方法
  16. Gaussdb,国产数据库的崛起
  17. JS-正则表达式匹配获取
  18. 国内SRC网站,拿走不送
  19. 汇文opac的openlink.php改造
  20. jq过渡收缩动画用js实现

热门文章

  1. 管理咨询公司全球前22排名
  2. 基于STM32的OLED 屏幕驱动
  3. 转载:50有用的JavaScript和jQuery技术和插件
  4. 区块链项目_数字资产控股DAH_清算结算
  5. 冬暖夏凉究竟香不香?带恒温的TaoTronics暖风机开箱实测
  6. 从球域采样分布分析360质量评估
  7. Session.Abandon()的用法
  8. 手机web字体css设置,手机web字体css怎么设置微软雅黑
  9. AM使用指南之一:Transaction和DBTransaction的区别与联系
  10. 《深度学习--基于python的理论与实现》学习笔记6:第三章神经网络(2)