2015-07-21 24 views
0

的ThreadA通过这个片段是否调用pthread_mutex_lock有之前发生的语义

{ 
    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. threadA --- 1
  2. threadA --- 2
  3. threadB --- 3
  4. threadB --- 4

可以在threadB "int tmp = global_a;"代码中看到什么的ThreadA设定在"global_a = 100;"

任何建议是值得欢迎的。

回答

1

pthread_mutex_lock并不妨碍以前的指令要在它后面下单。

类似的,pthread_mutex_unlock不会阻止跟着指令在它之前被排序。

但是:

  1. ThreadA中global_a = 100之前发生pthread_mutex_unlock(&b_mutex)

  2. 在线程B pthread_mutex_lock(&b_mutex)发生在int tmp = global_a;

如果你观察

  • pthread_mutex_unlock(&b_mutex) ThreadA中pthread_mutex_lock(&b_mutex)在threadB之前发生。
  • (换言之,threadB aquires锁定的ThreadA释放后),然后

    global_a = 100; ThreadA中之前发生int tmp = global_a;在threadB。所以,最后一个看到第一个的效果。

    什么POSIX标准说:

    至于POSIX标准同步的细节,我发现的唯一参考值(和其他人参考)约为Memory Synchronization短章。它说,pthread_mutex_lock(和其他一些功能)

    同步内存相对于其他线程

    某人的解释为完全内存屏障 garantee,其他人(和我)喜欢思考一些经典 garantees当锁定和等待动作提供内存获取语义,解锁和通知的 - 内存释放语义。参见,例如,这个mail

    没有之前发生在POSIX项。但它可以像往常一样定义,考虑到内存订单保证(在一个人的说明中)。

    +0

    证明是伟大的,但如果是这样定义的**之前发生**和** ** transitiviy通过**的之前发生**与'pthread_mutex_lock'和'pthread_mutex_unlock'?我有谷歌,但没有。你能告诉我一些关于它的参考吗? – Alex

    +0

    我在我的答案中添加了一些参考。 POSIX没有定义*发生前*期限,但它可以根据内存顺序保证来定义。 – Tsyvarev

    1

    如果您可以保证执行顺序 - 当是。如果你能保证执行顺序,你甚至不需要锁定某些体系结构。

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

    而且你编译器可制动的事情为好。所以把你的变量声明为volatile。

    +0

    最后用“所以声明你的变量为volatile”,你的意思是可能是threadB“int tmp = global_a;” **不能**看到在“global_a = 100;”处设置了什么线程 – Alex

    相关问题