锁和原子操作CAS的底层实现

案例:

        买火车票时,有个座位号,第几排第几个座,一排五个座位,买一个座位少一个座位,通过count++%5觉得了买的票在第几个座位,count++/5决定了在第几排;假设开十个线程;

        通过如下代码创建线程:     

在linux内核中没有进程线程之分,统一叫做task_struct,当调用pthread_create函数时,创建task_struct,创建这个结构体后的状态是new,就绪,等待,执行,退出都是线程的状态;new这个状态是还没有运行的,将其加入到队列中,这个new状态和就绪状态是一样的状态;什么时候调度是由调度器本身所决定的,不是由我们所决定的;pthread_create函数执行后什么时候运行创建的线程是不确定的,线程创建后就加入到了就绪队列中等待着被执行;  当调度器发现创建的func线程没有被执行过的时候,这个线程从new状态开始被回调,并传入count参数;调用pthread_join等待对应线程执行完返回pthread_join再往下执行,pthread_join函数是条件等待;

当有多个线程时对count++时对应的汇编代码,会出现线程1的汇编代码没有执行完,线程2就接着执行的情况;

如何解决上述问题呢? 

1、互斥锁ptread_mutex_t,可以干其他事情,获得锁再执行;

2、自旋锁pthread_spinlock_t,不会干其他事情,死等直到获得锁再执行;

3、原子操作 ,即能用一条指令执行不可分割;将count++分割成汇编代码封装到inc函数中,成为不可分割的整体,如下汇编代码;

 互斥锁和自旋锁和原子操作在这种场景下哪种更好;原子操作最快,所用时间最短;

下图CAS即比较后赋值,单例模式中使用这种方式实现原子操作’

原子操作的经典几个如add,sub,inc,dec,cas;

4、cpu亲缘性

        如何更加高效的利用cpu,比如有4核cpu,我们应该创建多少个线程;我们可以创建4个线程分别绑定到绑定到每个cpu上面;操作系统提供了固定的做法;

        通过cpu_set_t做粘合,比如4个cpu,进程或线程需要绑定哪个cpu,就将cpu_set_t对应位设置为1;绑定后进程或线程就只在对应cpu上运行;

上面代码中,cpu_set_t设置cpu组,这里时4个cpu,然后通过CPU_ZERO把mask清空,然后对进程self_id取模并使用这个值对mask对应位置1;然后通过sched_setaffinity对进程和cpu做粘合;粘合和进程就会只在对应cpu上运行;两个进程可以绑定在一个cpu上面;当一个进程有多个线程时,绑定的是主线程,子线程得通过子线程id去绑定cpu;

5、shmem,共享内存的做法;

        一个大文件,如何快速的读到内存中;把文件通过mmap映射到内存中,然后开启多个线程去读数据;

        mmap为什么快?磁盘的数据读到内存中通常通过cpu参与一一执行;而mmap映射是通过dma的方式,当我们一开始数据就已经到内存中了;dma是磁盘和内存间数据传输的一种方式,cpu不用参与;我们所说的零拷贝,是cpu不参与;mmap是实现共享内存的一种方式;

        可通过shm一系列接口实现映射内存;对应nginx代码如下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值