关于线程同步与互斥

https://www.cnblogs.com/xuejiale/p/10822896.html

 

线程之间通信的两个基本问题是互斥和同步。

  • 线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。
  • 线程互斥是指对于共享的操作系统资源(指的是广义的”资源”,而不是Windows的.res文件,譬如全局变量就是一种共享资源),在各线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。

线程互斥是一种特殊的线程同步。实际上,互斥和同步对应着线程间通信发生的两种情况:

  • 当有多个线程访问共享资源而不使资源被破坏时;
  • 当一个线程需要将某个任务已经完成的情况通知另外一个或多个线程时。

从大的方面讲,线程的同步可分用户模式的线程同步和内核对象的线程同步两大类。

  • 用户模式中线程的同步方法主要有原子访问和临界区等方法。其特点是同步速度特别快,适合于对线程运行速度有严格要求的场合。
  • 内核对象的线程同步则主要由事件、等待定时器、信号量以及信号灯等内核对象构成。由于这种同步机制使用了内核对象,使用时必须将线程从用户模式切换到内核模式,而这种转换一般要耗费近千个CPU周期,因此同步速度较慢,但在适用性上却要远优于用户模式的线程同步方式。

 

临界区、互斥体、事件和信号量都可以实现线程互斥.但如果仅仅需要实现互斥功能,推荐前两种。 

两者的区别:
1、临界区只能用于进程内的线程互斥,性能较好。
2、互斥体属于内核对象,可以用于进程间的线程互斥,性能较差。
3、线程在没有正常退出互斥区而意外终结时,互斥体可以复位,但临界区不行.。

 

线程同步:当有多个线程同时执行时,可能需要线程按照一定的顺序执行,比如:线程A负责将要处理的数据读取到内存中,而线程B负责分析这些数据,此时,应该是线程A执行完毕再执行线程B才有意义,这个时候就需要进行线程的同步控制。
 

可以用于线程同步控制的对象:事件和信号量。

两者的区别:
1、都是内核对象,使用完毕后应该关闭句柄。
2、信号量可以用于相当复杂的线程同步控制.。

分析:通过为售票的核心代码段加互斥锁使得其变成了一个原子性操作!不会被其他线程影响

 

二.条件变量(事件通知)

我们需要这样一种方法:当线程在等待满足某些条件时使线程进入睡眠状态,一旦条件满足,就换线因等待满足特定条件而睡眠的线程。

如果我们能够实现这样一种方法,程序的效率无疑会大大提高,而这种方法正是条件变量!

 

pthread_cond_t qready=PTHREAD_COND_INITIALIZER;   //cond   条件变量
pthread_mutex_t qlock=PTHREAD_MUTEX_INITIALIZER;  //mutex  互斥锁

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)

等待条件有两种方式:条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),其中计时等待方式如果在给定时刻前条件没有满足,则返回ETIMEDOUT,结束等待,其中abstime以与time()系统调用相同意义的绝对时间形式出现,0表示格林尼治时间1970年1月1日0时0分0秒。

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

 

激发条件有两种形式,pthread_cond_signal()激活一个等待该条件的线程,存在多个等待线程时按入队顺序激活其中一个;而pthread_cond_broadcast()则激活所有等待线程。

//pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx,
//然后阻塞在等待队列里休眠,直到再次被唤醒
//(大多数情况下是等待的条件成立而被唤醒,唤醒后,
//该进程会先锁定先pthread_mutex_lock(&mtx);,
//再读取资源用这个流程是比较清楚的
/*block-->unlock-->wait()return-->lock*/

信号量(sem)和互斥锁的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程进入临界区
1)信号量初始化

int sem_init(&sem,pshared,v)

pshared为0表示这个信号量是当前进程的局部信号量

pshared为1表示这个信号量可以在多个进程之间共享

v为信号量的初始值

成功返回0,失败返回-1

2)信号量值的加减

int sem_wait(&sem):以原子操作的方式将信号量的值减去1

int sem_post(&sem):以原子操作的方式将信号量的值加上1

3)对信号量进行清理

int sem_destory(&sem)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值