C多线程开发补充3

线程同步另外几种方式:自旋锁,信号量,关卡

自旋锁:

自旋锁适用的情况:锁被其他线程短期持有(很快会被释放),而且等待该锁的线程不希望在阻塞期间被取消调度,因为这会带来一些开销。

自旋锁与互斥锁的区别:

互斥锁通过休眠的方式来阻塞线程。(线程被暂时取消调度,切换至其他可运行的线程)

自旋锁通过忙等的方式来阻塞线程。(线程不会被取消调度,一直处于运行状态)

应用:

非抢占式内核中非常有用:比如在非抢占式内核中,中断处理程序是不能被休眠的,它们唯一可以使用的同步原语只有自旋锁。

用户级并不十分有用:在分时调度类中运行的用户级线程可以被取消调度 - 当它的时间片用完或有一个更高有效级的线程到来的时候。

自旋锁初始化:
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);

参数:
    lock : 自旋锁变量指针

    pshared : 自旋锁的只有一个属性,pshared代表线程进程共享同步属性,它指示了自旋锁如何获得。
              pshared = PTHREAD_PROCESS_SHARED : 自旋锁可以被访问该锁的底层内存的线程获得,即使这些线程来自于不同的进程
              pshared = PTHREAD_PROCESS_PRIVATE : 只能被本进程内初始化的线程获取。

返回值:成功返回0,失败返回错误代码。

自旋锁枷锁

int pthread_spin_lock(pthread_spinlock_t *lock);

int pthread_spin_trylock(pthread_spinlock_t *lock);

返回值:成功返回0,失败返回错误代码。

要给自旋锁枷锁,可以调用lock和trylock。pthread_spin_lock()在获得锁之前,线程会一直自旋;pthread_spin_trylock()时线程不自旋,如果自旋锁不能立即获得,返回错误EBUSY。

自旋锁解锁

不论使用lock还是tryklock上锁,都可以调用pthread_spin_unlock()解锁

int pthread_spin_unlock(pthread_spinlock_t *lock);

返回值:成功返回0,失败返回错误代码。

注意:不要调用会在持有自旋锁期间休眠的函数,由于自旋等待可能会浪费大量的CPU资源。

 信号量:

是一种特俗的变量,一个信号量有一个相关联的整数值,该整数值大于等于0,它可以被增加或减小,但被其的关键访问被保证是原子操作。

通过调用sem_wait对相应的整数值减1,即通常所说的若当前的信号量的值等于0,则该操作会阻塞线程。

另外一种通过sem_post对相应值加1,即通常说的。

信号量分类:信号量可作如下分类:

二元灯:灯亮/灯灭两种状态,取值1/0,这是与互斥锁相似的

多元灯:大于1的灯数,表示有多个资源,成为多元灯

信号量即可用于进程间同步也可以用于线程间同步。

信号量使用的头文件semaphore.h

初始化函数

int sem_init(sem_t *sem, int pshared, unsigned int value); 

sem : 信号量变量指针
pshared : 信号量类型,为0表示为当前进程的局部信号量,为1表示可以在多个进程间共享
value : sem的初始值

返回值:调用成功返回0,失败返回-1

信号量减1

int sem_wait(sem_t *sem);  

功能:以原子操作的方式将信号量的值减1

参数:
    sem:sem_init()初始化的信号量

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

信号量加1 

int sem_post(sem_t *sem);  

功能:以原子操作的方式将信号量的值加1

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

信号量清理函数

int sem_destroy(sem_t *sem);

返回值:成功返回0,失败返回-1
互斥锁用于互斥,信号量用于同步。

这是互斥锁/互斥量和信号量/信号灯的根本区别。
1.互斥量的值只能为0/1,信号量的值可以大于1。

即互斥量只能实现一个资源的互斥访问,但信号量可以实现多个资源的多线程互斥和同步。
当信号量为单值信号量,也可以完成一个资源的互斥访问。
互斥量的加锁和解锁操作必须由同一个线程分别对应使用,而信号量可以由一个线程释放,另一个线程得到。

互斥和同步的概念:
互斥:某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。互斥访问是无序访问,无法限制访问者对资源的访问顺序。
同步:在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

信号量例子

 

 

关卡

关卡是一种同步机制,可以协调多个并行工作的线程,关卡使每一个线程等待直至所有合作的线程都到达了同一点,然后再从一个点开始继续执行。

pthread_join()函数是一个关卡机制,它使一个线程等待另一个线程的结束。比如在主线程中等待所有子线程的结束然后释放资源结束程序。

关卡比pthread_join()更一般化,它允许任意数量的线程等待

关卡使用的头文件 pthread.h

初始化函数

int pthread_barrier_init( pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned int count);

参数:
    barrier: 关卡变量指针
    attr: 关卡属性,NULL为使用默认属性
    count: 指定在所有线程继续运行之前,必须达到该关卡的线程的个数

返回值:成功返回0,失败返回出错编号

等待函数

int pthread_barrier_wait( pthread_barrier_t *barrier);

返回值:成功返回0或PTHREAD_BARRIER_SERIAL_THREAD,失败返回出错编号
       PTHREAD_BARRIER_SERIAL_THREAD: 返回该值的线程为主线程,负责处理所有线程完成工作后的结果

说明:在到达关卡的线程数量没有达到count个数时,调用pthread_barrier_wait()函数的线程都会休眠,直到count个线程的最后一个线程调用pthread_barrier_wait()函数时,所有线程都被唤醒。

资源释放函数

int pthread_barrier_destroy( pthread_barrier_t *barrier);

返回值:成功返回0,失败返回错误编号

初始化关卡对象时,指定的线程数量为工作线程量加1,加1是加上主线

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值