6.【多线程 任务同步】

1. 概念

线程同步概念:(唯一线程占用,用完后,其他线程才能用)

当有一个线程 在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作, 其他线程才能对该内存地址进行操作,而其他线程又处于等待状态。

临界资源:一次仅允许 一个进程/线程 访问的共享资源

临界区:访问 临界资源 的 代码

惊!线程同步居然讲的这么详细:信号量、互斥锁、条件变量、读写锁_互斥锁、读写锁、信号量、条件变量的效率_WolfOnTheWay的博客-CSDN博客

2. (互斥)信号量(线程间:用信号量 去控制 线程对内存 的访问)

信号量:通过信号量实现同步操作:由信号量来决定线程是继续运行还是阻塞等待

信号量代表某一类资源,其值表示系统中该资源的数量

信号量值>0:表示有资源可以用,可以申请到资源,继续执行程序

信号量值<=0:表示没有资源可以用,无法申请到资源,阻塞

信号量是一个受保护的变量,只能通过三种操作来访问:

  1. 初始化sem_init
  2. P操作(申请资源 -1)sem_wait
  3. V操作(释放资源 +1)sem_post

2.1. 初始化信号量 sem_init

int  sem_init(sem_t *sem,  int pshared,  unsigned int value)  
功能:初始化信号量   
参数:
	sem:初始化的信号量对象
    pshared:信号量共享的范围(0: 线程间使用   非0:进程间使用)
    value:信号量初值
返回值:
	成功 0
    失败 -1

2.2. 申请消耗资源 sem_wait

int  sem_wait(sem_t *sem)  
功能:申请消耗资源  P操作 (-1)
参数:sem:信号量对象
返回值:
	成功 0
    失败 -1
    
注:此函数执行过程:
	当信号量的值大于0时,表示有资源可以用,则继续执行,同时对信号量减1;
	当信号量的值等于0时,表示没有资源可以使用,函数阻塞

2.3. 释放增加资源 sem_post

int  sem_post(sem_t *sem)   
功能:释放增加资源  V操作      
参数:sem:信号量对象
返回值:
	成功 0
    失败 -1
    
注:释放一次信号量的值加1,函数不阻塞

2.4. 销毁已经初始化的信号量 sem_destroy

int sem_destroy(sem_t *sem);
功能:用于销毁已经初始化的信号量

注意:
	在调用之前 需要确保 没有线程正在使用该信号量,否则会导致未定义的行为。
	销毁信号量后,这个信号量将不能再被使用,除非之后重新初始化。

2.5. 案例

3. 互斥 互斥锁(又叫互斥量)

临界资源:一次 仅允许一个进程 所使用的资源

临界区:指的是 一个访问共享资源的 程序片段

互斥:

多个线程在访问临界资源时,同一时间 只能允许一个线程访问

互斥锁(又称互斥量):从本质上来说是一把锁

临界资源默认 没有 上锁:

不管哪个线程要用该临界资源,都需要先 抢着上锁才能用

资源仅被唯一上锁后才可使用,用完释放锁

其他想抢占使用该资源的进程会被阻塞,直到任一个线程又抢到锁。

1. 互斥锁(互斥量)是一种 通过互斥 实现同步 的机制,用于保护共享资源。

2. 每个临界资源都由一个互斥锁来保护。

3. 线程必须 先获得互斥锁 才能访问临界资源。

4. 如果 无法获得锁,线程将被阻塞,直到获得锁为止。

5. 互斥量本质上是一把锁,加锁后 其他 试图加锁的线程 将被阻塞,直到 当前线程 释放锁。

6. 如果多个线程 在释放互斥锁, 只有一个线程可以重新获取锁并继续推进,其他进程被阻塞。

3.1. 初始化锁 pthread_mutex_init

int  pthread_mutex_init(pthread_mutex_t  *mutex, pthread_mutexattr_t *attr)  
功能:初始化互斥锁  
参数:
	mutex: 互斥锁	   //  哪把锁
    attr:  互斥锁属性  //  NULL表示缺省属性
返回值:
	成功  0
    失败 -1

3.2. 申请锁(上锁)pthread_mutex_lock 和 pthread_mutex_trylock区别

int  pthread_mutex_lock(pthread_mutex_t *mutex)   
    //阻塞的,直到 能申请到上锁
    
功能:申请互斥锁     
参数:mutex:互斥锁
返回值:
	成功  0
    失败 -1
int pthread_mutex_trylock(pthread_mutex_t *mutex) 
    // 不阻塞,抢不到 就立即返回一个值 来描述互斥锁的状况
    
注:和pthread_mutex_trylock区别:
	pthread_mutex_lock 是阻塞的;
	pthread_mutex_trylock 不阻塞,如果申请不到锁会立刻返回

3.3. 死锁(申请上锁时候发生)

死锁举例:

  1. 线程试图对同一个互斥量A加锁两次。
  2. 线程1拥有A锁,请求获得B锁;线程2拥有B锁,请求获得A锁
3.3.1. 概念

是指两个或两个以上的进程/线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去

3.3.2. 死锁产生的四个必要条件
  1. 互斥使用:即当资源被一个线程使用(占有)时,别的线程不能使用
  2. 不可抢占:资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
  3. 请求和保持:即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
  4. 循环等待:即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

注意:当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。

3.4. 释放锁(解锁)pthread_mutex_unlock

int  pthread_mutex_unlock(pthread_mutex_t *mutex)   
功能:释放互斥锁     
参数:mutex:互斥锁
返回值:
	成功  0
    失败 -1

3.5. 销毁锁 pthread_mutex_destroy

int  pthread_mutex_destroy(pthread_mutex_t  *mutex)  
功能:销毁互斥锁     
参数:mutex:互斥锁

3.6. 案例

4. 条件变量

4.1. 概念

条件变量 可以使 线程睡眠 去 等待 某个条件 的发生

4.2. 初始化条件变量 pthread_cond_init

int pthread_cond_init(pthread_cond_t *restrict cond,
                      const pthread_condattr_t *restrict attr);
功能:初始化条件变量
参数:
	cond:是一个指向结构pthread_cond_t的指针
    restrict attr:是一个指向结构pthread_condattr_t的指针,一般设为NULL
    
返回值:
	成功:0 
 	失败:非0

4.3. 等待信号的产生 pthread_cond_wait

int pthread_cond_wait(pthread_cond_t *restrict cond,
                      pthread_mutex_t *restrict mutex);
功能:等待信号的产生
参数:
	restrict cond:要等待的条件(哪个条件变量)
    restrict mutex:对应的锁(哪个互斥锁/量)
返回值:
	成功:0
 	失败:不为0
  
注:和互斥锁用法一致,区别在互斥锁是主动抢占资源,条件变量是被通知去使用资源
	1.当没有条件产生时,函数会阻塞,同时会将锁解开,任务进入睡眠,
 		直至被pthread_cond_signal或者pthread_cond_broadcast函数唤醒。
	2.如果等待到 条件产生,函数被唤醒,会 结束阻塞 同时进行上锁。
        程序pthread_cond_wait会继续执行,不再睡眠,同时对mutex进行加锁

理解:

没条件产生时,与自己无关,保持阻塞不向下执行,不上锁

有条件产生时,自己抢占资源,上锁,向下执行

4.4. 给 条件变量 发送信号 pthread_cond_signal

int pthread_cond_signal(pthread_cond_t *cond);
功能:给条件变量发送信号
参数:cond:条件变量值
返回值:
	成功:0,
 	失败:非0

注: 先保证 阻塞等待条件信号的 情况,之后才可发信号
	必须等待pthread_cond_wait函数先执行,再产生条件才可以
int pthread_cond_broadcast(pthread_cond_t * cond);
功能:唤醒所有睡眠的条件变量

4.5. 摧毁一个条件变量 pthread_cond_destroy

int pthread_cond_destroy(pthread_cond_t *cond);
功能:将条件变量销毁
参数:cond:条件变量值
返回值:
	成功:0, 
 	失败:非0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值