【线程篇】线程间同步之信号量、互斥锁

本文介绍了线程的概念及其与进程的区别,重点探讨了线程同步中的信号量和互斥锁。信号量用于限制并发访问资源的数量,而互斥锁则保证同一时间只有一个线程访问关键代码段。还提到了自旋锁及其优缺点,并讨论了无锁编程中的CAS操作及其应用,以及ABA问题和循环CAS的开销问题。
摘要由CSDN通过智能技术生成

线程:进程内部的一条执行路径(序列)

什么是线程什么是进程,进程和线程的区别?

进程是一个正在运行的程序,是系统进程资源分配的基本单位

线程是进程内部的一条执行路径,是系统调度的基本单位

Pthread.h头文件  -lpthread 库

理解多线程的并发运行?

并发运行:单个或多个处理器

并行:需要多处理器

线程同步(线程间通讯):信号量,互斥锁,条件变量,读写锁

信号量和互斥锁区别?

mutex,互斥锁,用于序列化对一部分可重入代码的访问,这些代码不能由多个线程同时执行

semaphore,信号量,将共享资源的并发用户数限制为最大数量

 

互斥锁:主要解决互斥性问题,相当于一个初值为1的二值信号量,更方便

Mutex:假设我们有关键部分线程T1想要访问它然后它遵循以下步骤:

1.锁

2.使用关键部分

3.开锁

二进制信号量:它基于信令等待和信号工作。等待(s)将“s”值减少一个通常“s”值用值“1”初始化,信号(s)将“s”值增加1。如果“s”值为1表示没有人使用临界区,则值为0表示临界区正在使用中。假设线程T2正在使用临界区,那么它遵循以下步骤:

1.wait(s)//最初s值在调用之后等于它的值减1,即0

2.使用关键部分

3.signal(s)//现在s值增加,变为1

自旋锁:内核中同步时使用的,忙等待的锁

对于互斥锁,如果资源已经被占用,资源申请者只能进入睡眠状态;自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋锁的保持者已经释放了锁。

自旋锁的缺陷:1.死锁2.过多占用CPU资源

忙等待的锁:一直占用CPU进行测试,需要多处理器

非忙等待的锁:处于阻塞等待

无锁队列:

CAS(C++)Compare And Set:一个安全检查

CAS是解决多线程并行情况下使用锁造成性能损耗的一种机制

内存位置(V)、预期原值(A)、新值(B):如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。

1.无锁同步CAS:

当我们如果只是由于一条代码出现了线程安全问题,比如说多个线程都要往一个队列中的尾部插入一个元素,那么我们的tail->next=newnode;是我们一条必要的代码。但是当我们拿到tail的时候,在执行这条指令前,其他线程率先在原来的队列尾部插入元素,这就会引起tail的失效,因为tail的值变了。这种情况下如果我们加入了锁只是为了控制一条临界代码,那么开销就太大了。因此我们就引入了我们cpu的CAS操作。

2.我们将CAS用在队列当中构造一个无锁队列来说明以上CAS的具体用途

EnQueue(x) //进队列Q

{

    //准备新加入的结点数据

    q = new record();

    q->value = x;

    q->next = NULL;

 

do

{

        p = tail; //取链表尾指针的快照

    } while( !CAS(p->next, NULL, q)); //如果没有把结点链在尾指针上,再试 如果p->next == NULL 则 p->next = q;其他线程也进不来

 

    CAS(tail, p, q); //置尾结点 看尾是不是p,是则更新tail = q,让其他线程可以进来

}

 

DeQueue() //出队列

{

    do{

        p = head;

        if (p->next == NULL){

            return ERR_EMPTY_QUEUE;

        }

    while( !CAS(head, p, p->next));

    return p->next->value;

}

CAS缺点:

1.存在ABA问题因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A-2B-3A。

2.循环时间长开销大自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。

3. 只能保证一个共享变量的原子操作对一个共享变量执行操作时,我们可以使用循环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候就可以用锁,或者有一个取巧的办法,就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i=2,j=a,合并一下ij=2a,然后用CAS来操作ij。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值