0

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

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

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

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

请问我的理解对吗?

11月17日提问
1 个回答
1

已采纳

我觉得你理解得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);
}

撰写答案

推广链接