0

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
}

并假设从观察者的角度来看,执行顺序确实是

  1. 线程A --- 1
  2. 线程A --- 2
  3. 线程B --- 3
  4. 线程B --- 4

threadB 的代码可以"int tmp = global_a;"看到 threadA 的设置"global_a = 100;"吗?

欢迎任何建议。

4

2 回答 2

1

pthread_mutex_lock不妨碍在它之后订购先前的说明。

类似的,pthread_mutex_unlock不妨碍在它之前订购遵循的指令。

但:

  1. 在线程 Aglobal_a = 100 发生之前 pthread_mutex_unlock(&b_mutex)

  2. 在 threadBpthread_mutex_lock(&b_mutex) 发生之前 int tmp = global_a;

如果你观察

  1. pthread_mutex_unlock(&b_mutex)在线程 A 中发生 pthread_mutex_lock(&b_mutex)在线程 B 中。

(换句话说,threadB在 threadA 释放获取锁),那么

global_a = 100;在线程 A 中发生 int tmp = global_a;在线程 B 中。所以,最后一个看到第一个的效果。

POSIX 标准是怎么说的:

至于 POSIX 标准中的同步细节,我发现的唯一参考(以及其他参考)是关于Memory Synchronization的简短章节。它说pthread_mutex_lock(和其他一些功能)

相对于其他线程同步内存

有人将此解释为完整的内存屏障保证,其他人(和我)更喜欢考虑一些经典的保证,当锁定和等待动作提供内存获取语义,解锁和通知那些 -内存释放语义时。参见,例如,这封邮件

POSIX中没有happens-before术语。但它可以像往常一样定义,考虑到内存顺序保证(在一个人的解释中)。

于 2015-07-21T22:10:49.000 回答
1

如果你能保证执行顺序——当是。如果你能保证执行顺序,你甚至不需要在某些架构上加锁。

锁实际上做了三件事: 1. 不允许不同的代码同时执行。看。这里没有提到内存。它只是保证不同线程中的代码不会同时执行。2. 在某些架构上,它会插入缓存一致性指令。这迫使多个处理器系统将数据刷新到实际内存中。但是您现在不必担心这种情况,因为“如果对同一内存位置的所有写入都以某种顺序执行,则多处理器是缓存一致的” 3. 它插入内存屏障指令。它是针对处理器的,告诉它不要弄乱执行顺序。

你的编译器也可能会刹车。因此,将您的变量声明为 volatile。

于 2015-07-21T23:14:58.207 回答