美文网首页
mutex, spinlock, cas

mutex, spinlock, cas

作者: congchp | 来源:发表于2021-08-15 11:07 被阅读0次

    1.多线程数据共享,资源保护方法:
    1)mutex
    如果获取不到锁,让出CPU,将线程加入等待队列。

    任务耗时比上下文切换要长
    

    2)spinlock
    如果获取不到锁,则继续死循环检查锁的状态,如果是lock状态,则继续死循环,否则上锁,结束死循环。

    (1)任务不能存在阻塞 (2)任务耗时短,几条指令
    

    3)无锁CAS(Compare and Swap)
    比较并交换,是一种原子操作

    bool CAS( int * pAddr, int nExpected, int nNew )
    atomically {
        if ( *pAddr == nExpected ) {
            *pAddr = nNew ;
            return true ;
        } else
        return false ;
    }
    

    2.操作的原子性

    #include <stdio.h>
    
    int i = 0;
    // gcc -S 1_test_i++.c
    int main(int argc, char **argv)
    {
        ++i;
        return 0;
    }
    

    ++i 不是原子操作
    汇编代码

        movl    i(%rip), %eax //把i从内存加载到寄存器
        addl    $1, %eax //把寄存器的值加1
        movl    %eax, i(%rip) //把寄存器的值写回内存
    
    static int lxx_atomic_add(int *ptr, int increment)
    {
        int old_value = *ptr;
        __asm__ volatile("lock; xadd %0, %1 \n\t"
                         : "=r"(old_value), "=m"(*ptr)
                         : "0"(increment), "m"(*ptr)
                         : "cc", "memory");
        return *ptr;
    }
    

    3.原子操作
    gcc、g++编译器提供了一组原子操作api

    bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
    

    C++11也提供了一组api,定义在<atomic>中

    X86架构原子操作实现

    static int lxx_atomic_add(int *ptr, int increment)
    {
        int old_value = *ptr;
        __asm__ volatile("lock; xadd %0, %1 \n\t"
                         : "=r"(old_value), "=m"(*ptr)
                         : "0"(increment), "m"(*ptr)
                         : "cc", "memory");
        return *ptr;
    }
    

    4.无锁队列的实现
    无锁队列适用于队列push、pop非常频繁的场景,效率要比mutex高很多

    相关文章

      网友评论

          本文标题:mutex, spinlock, cas

          本文链接:https://www.haomeiwen.com/subject/fptzvltx.html