1. 线程同步:

当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图。当某个线程可以修改变量,而其他线程也可以读取或者修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量的存储内容的时候不会访问到无效的数值;

当一个线程修改变量时,其他线程在读取这个变量的值的时候可能看到不一致的数据,在变量修改时间多余一个存储器周期的处理器结构中,当存储器读与存储器写这两个周期交叉时,这种潜在的不一致性就会出现些;

2. 互斥量:

从本质上来说互斥量是一把锁,对互斥量进行加锁以后,任何其他视图再次对互斥量加锁的线程将会阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥量加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等它重新变为可用,这种方式下,只有一个线程可以向前执行;

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutex, 
const pthread_mutexattr_t *restrict attr); //默认属性可以设置为NULL int pthread_mutex_destroy(pthread_mutex_t *mutex); ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex); //如果不希望阻塞,可以使用trylock尝试加锁,锁住返回0,或者返回EBUSY

int pthread_mutex_unlock(pthread_mutext_t *mutex);

ret-成功返回0 失败返回错误编号

产生死锁:

(1) 如果线程视图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态;

(2) 程序中使用多个互斥量,如果允许一个线程一直占有第一个互斥量,并且在视图锁住第二个互斥量时处于阻塞状态,但是拥有第二个互斥量的线程也在视图锁住第一个互斥量,这样就会发生死锁;

避免死锁:

(1) 可以通过小心的控制互斥量加锁的顺序来避免死锁的发生。

(2) 如果不能获取锁,可以先释放占有的锁,过一段时间再试。

3. 读写锁:

读写锁与互斥量类似,不过允许更高的并行性。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁;

读写锁非常适合对数据结构读次数远大于写的情况。

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr); //默认属性传空 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

ret-成功返回0 失败返回错误编码EBUSY

4. 条件变量:

条件变量与互斥量一起使用,允许线程以无竞争方式等待特定的条件发生。条件本身是由互斥量保护的,线程改变条件状态前必须先锁住互斥量,其他线程在获得互斥量之前不会觉察到这种改变,因为必须锁定互斥量以后才能计算条件。

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond,
pthread_condattr_t *restrict attr); int ptherad_cond_destroy(pthread_cond_t *cond); ret-成功返回0 失败返回错误编号
#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutext_t *restrict mutex); int pthread_cond_timewait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict timeout); ret-成功返回0 失败返回错误编号

传递给xxxwait的互斥量对条件进行保护,调用者把锁住的互斥量传递给函数。函数把调用线程放到等到条件的线程列表上,然后对互斥量解锁,这两个操作是原子的。这样就关闭了条件检查和线程进入休眠状态等待条件改变这两个操作直接的时间通道,这样线程就不会错误条件的任何变化。xxxwait返回时,互斥量再次被锁住;

#include <pthread.h>

int pthead_cond_signal(pthread_cond_t *cond); //通知某个进程,也可以通知不止一个线程

int pthread_cond_broadcast(pthread_cond_t *cond); //通知所有线程

ret-成功返回0 失败返回错误编号

注意要在条件变量改变之后发生信号;

Linux线程同步的更多相关文章

  1. 【转】 Linux 线程同步的三种方法

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的 ...

  2. Linux线程同步之读写锁(rwlock)

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...

  3. linux线程同步(1)-互斥量

    一.概述                                                   互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...

  4. Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

    互斥锁 #include <cstdio> #include <cstdlib> #include <unistd.h> #include <pthread. ...

  5. Linux线程同步:条件变量

    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用.使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化.一旦其它 ...

  6. Linux线程同步——条件变量

    互斥锁是用来给资源上锁的,而条件变量是用来等待而不是用来上锁的. 条件变量用来自动阻塞一个线程,直到某特殊情况发生为止. 通常条件变量和互斥锁同时使用. 和条件变量使用有关的几个重要函数: int p ...

  7. linux线程同步实例

    [Linux多线程]三个经典同步问题 - 神奕的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/lisonglisonglisong/article/details ...

  8. linux 线程同步(二)

    信号量 信号量是相互排斥锁的升级版把相互排斥锁中1变成了n.举个简单的样例:如果如今有10个人,有一部手机.这10个人都竞争来使用手机打电话这就是相互排斥锁.对于信号量,如今可能是有4部手机,这10个 ...

  9. linux线程同步(5)-屏障

    一.概述                                                    barrier(屏障)与互斥量,读写锁,自旋锁不同,它不是用来保护临界区的.相反,它跟条 ...

随机推荐

  1. jsp当做第二个servlet request的生命周期 请求 响应 不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束 request的域消失

    jsp当做第二个servlet  request的生命周期   请求 响应  不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束  request的域消失

  2. bzoj4753[JSOI2016]最佳团体

    题意:01分数规划,但可选的数字之间存在森林形的依赖关系(可以认为0号点是个虚根,因为并不能选). 虽然有森林形的依赖关系,但还是可以套分数规划的思路,二分答案k,判断是否存在一个比值大于k的方案 即 ...

  3. BZOJ4241 历史研究(莫队)

    如果分块的话与区间众数没有本质区别.这里考虑莫队. 显然莫队时的删除可以用堆维护,但多了一个log不太跑得过. 有一种叫回滚莫队的trick,可以将问题变为只有加入操作.按莫队时分的块依次处理,一块中 ...

  4. NetScaler ‘Counters’ Grab-Bag!

    NetScaler ‘Counters’ Grab-Bag! https://www.citrix.com/blogs/author/andrewre/ https://www.citrix.com/ ...

  5. BZOJ3040:最短路——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3040 题意rt,使用pb_ds的堆解决本问题. 所以其实就是mark一下的. 不过有人确认过官方不 ...

  6. BZOJ4104 [Thu Summer Camp 2015]解密运算 【乱搞】

    题目链接 BZOJ4104 题解 我们将已知字符排序,由循环就可以得到一个对应关系 如样例就是: 0->第5行 1->第1行 1->第2行 1->第3行 1->第5行 2 ...

  7. React中的高阶组件,无状态组件,PureComponent

    1. 高阶组件 React中的高阶组件是一个函数,不是一个组件. 函数的入参有一个React组件和一些参数,返回值是一个包装后的React组件.相当于将输入的React组件进行了一些增强.React的 ...

  8. 【BZOJ 3569】DZY Loves Chinese II 随机化+线性基

    用到一个结论——[先建树,再给每个非树边一个权值,每个树边的权值为覆盖他的非树边的权值的异或和,然后如果给出的边存在一个非空子集异或和为0则不连通,否则连通](必须保证每条边的出现和消失只能由自己产生 ...

  9. Rabbitmq----基础使用

    ---------------rabbitmq的基础使用--------------- 查看消息队列信息 在安装好rabbitmq-server之后,启动服务 使用命令rabbitmqctl list ...

  10. dubbo在项目中的应用

    关于dubbo的使用,我们举个简单例子: 存在2个系统,A系统和B系统,A系统调用B系统的接口获取数据,用于查询用户列表. 在上一篇博文介绍了dubbo的创建,zookeeper的创建完成后,我们可以 ...