请问我对linux 互斥锁的理解对吗

之前最关键的一点没想明白,现在相同也测试过了,想问问大佬我的理解是不是对的。
比如我现在建立一个锁
pthread_mutex_t test_mutex;
要对应管理一个变量temp1

那么我的代码,必须要先lock然后读写temp1,这样才是规矩;
但是,如果temp1被直接写,这个锁也没有办法阻止。

之前理解为锁和变量会有注册函数,如果不获取锁,没办法对变量操作,现在实践下来,其实叫锁不是很恰当,因为实际上锁不住,我要直接对temp=1,谁也锁不住,所以理解上,应该理解成操作变量前的一个flag,表示当前是否会有操作冲突的意思。C语言本身是高级语言中的低级语言,如果高级语言的锁可能可以注册对应要锁的变量(我猜的),但是C要直接操作哪块内存是拦不住的,操作不当coredump后果自负。

然后我自己想的方法是,需要锁的变量,读写全部封装,代码规则上不许直接temp =xxx这样写法,全部用wirte_var()函数形式封装,在函数内部先获取锁再操作,这样就避免了多人协助时候的误操作。

请问我的理解对吗?

阅读 313
评论
    1 个回答
    • 1.5k

    我觉得你理解得OK。


    首先我们要知道在运行中的程序中到底意味着什么?它其实就是一段内存,上面记录了其状态是 locked 还是 unlocked,改变它的状态需要原子操作。如果原子操作?其实就是在修改时锁住总线(各种CPU体系会提供),这一点glibc已经提供的锁操作的接口已经做了,比如 pthread_mutex_lock, 这里面会锁住总线修改锁的状态。顺便说一句,atomic_t 那一系列接口也是这样。


    常见用法是将锁内嵌在要保护的结构内部,比如

    struct XXX
    {
        int a;
        int b;
        pthread_mutex_t lock;  //  <-- 这个结构
    }

    而在使用它时,用相应的方法:

    struct XXX xxx;
    
    set_a(struct XXX* pxxx, int val)
    {
        lock(pxxx->lock);
        pxxx->a = val;
        unlock(pxxx->lock);
    }

    不过,正如你说的, 你完全可以在其他线程直接去改写 pxxx->a = val,编译器绝对不会拦你,因为 a 和 lock 是完全独立的两个字段!

    或许你可以采用不对外暴露 XXX 结构的方法, 让外面看不到 struct XXX 的定义,这样自然外面就不能操作 pxxx->a 了,编译器会阻止。

    set_a(void* _pxxx, int val)
    {
        struct XXX* pxxx = (struct XXX* )_pxxx;
        
        lock(pxxx->lock);
        pxxx->a = val;
        unlock(pxxx->lock);
    }
      撰写回答

      登录后参与交流、获取后续更新提醒