threadA浏览此代码段
{
global_a = 100; // 1
{
pthread_mutex_lock(&b_mutex)
...
pthread_mutex_unlock(&b_mutex)
} // 2
}
threadB浏览此代码段
{
{
pthread_mutex_lock(&b_mutex)
...
pthread_mutex_unlock(&b_mutex)
} // 3
int tmp = global_a; // 4
}
并假设从观察者的角度来看,执行顺序确实是
threadB "int tmp = global_a;"
的代码能否看到"global_a = 100;"
处设置的threadA?
欢迎提出任何建议。
答案 0 :(得分:1)
pthread_mutex_lock
不会阻止以前的指令在其后面进行排序。
类似地,pthread_mutex_unlock
不会阻止在其之前订购跟随指令。
可是:
在threadA global_a = 100
发生之前 pthread_mutex_unlock(&b_mutex)
。
在threadB pthread_mutex_lock(&b_mutex)
发生之前 int tmp = global_a;
。
如果你观察
pthread_mutex_unlock(&b_mutex)
在threadB中 pthread_mutex_lock(&b_mutex)
之前发生。(换句话说,threadB在 threadA发布之后获取锁),然后
threadA中的 global_a = 100;
发生在threadB中的 int tmp = global_a;
之前。所以,最后一个看到了第一个的效果。
POSIX标准所说的内容:
至于POSIX标准中的同步细节,我发现的唯一参考(以及其他参考)是关于Memory Synchronization的简短章节。它说pthread_mutex_lock
(以及其他一些功能)
使内存与其他线程同步
有人将此解释为完全内存障碍保证,其他人(和我)更喜欢考虑一些经典保证,当锁定和等待动作提供内存获取时语义,解锁和通知 - 内存释放语义。例如,参见mail。
POSIX中没有发生在之前的术语。但它可以像往常一样定义,考虑到记忆顺序保证(在一个人的解释中)。
答案 1 :(得分:1)
如果可以保证执行顺序 - 当是的时候。如果您可以保证执行顺序,则甚至不需要锁定某些体系结构。
Lock实际上做了三件事: 1.不允许同时执行不同的代码。看到。这里没有提到记忆。它只是保证不同线程中的代码不会同时执行。 2.在某些体系结构上,它将插入缓存一致性指令。这迫使多处理器系统将数据刷新到真实存储器中。但你现在不应该担心这种情况导致“如果所有对同一内存位置的写操作都以某种顺序执行,则多处理器是缓存一致的” 3.它插入内存屏障指令。它是针对处理器的,告诉它不要乱用执行顺序。
此外,您的编译器也可能会制造东西。因此,将变量声明为volatile。