pthread_mutex_lock 是否具有 happens-before 语义
Does pthread_mutex_lock have happens-before semantics
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
}
并假设从观察者的角度来看执行顺序确实是
- 线程A --- 1
- 线程A --- 2
- 线程B --- 3
- 线程B --- 4
线程 B "int tmp = global_a;"
的代码可以看到线程 A 在 "global_a = 100;"
设置了什么吗?
欢迎提出任何建议。
pthread_mutex_lock
不会阻止 前面的 指令在它之后排序。
类似地,pthread_mutex_unlock
不会阻止 followed 指令在它之前被排序。
但是:
在线程A中global_a = 100
发生在之前pthread_mutex_unlock(&b_mutex)
.
在线程 B 中 pthread_mutex_lock(&b_mutex)
happens-before int tmp = global_a;
.
如果你观察
pthread_mutex_unlock(&b_mutex)
在 threadA 中 happens-before pthread_mutex_lock(&b_mutex)
在 threadB.
(换句话说,threadB 在 threadA 释放后获得锁),然后
global_a = 100;
在 threadA 中 happens-before int tmp = global_a;
在 threadB 中。所以,最后一个看到第一个的效果。
POSIX标准说的是什么:
至于 POSIX 标准中的同步细节,我找到的唯一参考(和其他参考)是关于 Memory Synchronization 的简短章节。它说 pthread_mutex_lock
(和其他一些功能)
synchronize memory with respect to other threads
有人将其解释为 完全内存屏障 保证,其他人(和我)更愿意考虑一些 经典 保证,当锁定和等待动作提供内存获取语义,解锁和通知-内存释放语义。参见,例如,这个 mail.
POSIX 中没有 happens-before 项。但它可以像往常一样定义,考虑到内存顺序保证(在一个人的解释中)。
如果你能保证执行顺序- 是的话。如果你能保证执行顺序,你甚至不需要锁定某些架构。
锁实际上做了三件事:
1.不要让不同的代码同时执行。看。这里没有提到内存。它只是保证不同线程中的代码不会同时执行。
2. 在某些架构上它会插入缓存一致性指令。这迫使多处理器系统将数据刷新到实际内存中。但是你现在不应该担心这个案例 "a multiprocessor is cache consistent if all writes to the same memory location are performed in some sequential order"
3.插入内存屏障指令。它是给处理器的,告诉它不要打乱执行顺序。
此外,您的编译器也可能会阻止某些事情。因此,将您的变量声明为易变的。
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
}
并假设从观察者的角度来看执行顺序确实是
- 线程A --- 1
- 线程A --- 2
- 线程B --- 3
- 线程B --- 4
线程 B "int tmp = global_a;"
的代码可以看到线程 A 在 "global_a = 100;"
设置了什么吗?
欢迎提出任何建议。
pthread_mutex_lock
不会阻止 前面的 指令在它之后排序。
类似地,pthread_mutex_unlock
不会阻止 followed 指令在它之前被排序。
但是:
在线程A中
global_a = 100
发生在之前pthread_mutex_unlock(&b_mutex)
.在线程 B 中
pthread_mutex_lock(&b_mutex)
happens-beforeint tmp = global_a;
.
如果你观察
pthread_mutex_unlock(&b_mutex)
在 threadA 中 happens-beforepthread_mutex_lock(&b_mutex)
在 threadB.
(换句话说,threadB 在 threadA 释放后获得锁),然后
global_a = 100;
在 threadA 中 happens-before int tmp = global_a;
在 threadB 中。所以,最后一个看到第一个的效果。
POSIX标准说的是什么:
至于 POSIX 标准中的同步细节,我找到的唯一参考(和其他参考)是关于 Memory Synchronization 的简短章节。它说 pthread_mutex_lock
(和其他一些功能)
synchronize memory with respect to other threads
有人将其解释为 完全内存屏障 保证,其他人(和我)更愿意考虑一些 经典 保证,当锁定和等待动作提供内存获取语义,解锁和通知-内存释放语义。参见,例如,这个 mail.
POSIX 中没有 happens-before 项。但它可以像往常一样定义,考虑到内存顺序保证(在一个人的解释中)。
如果你能保证执行顺序- 是的话。如果你能保证执行顺序,你甚至不需要锁定某些架构。
锁实际上做了三件事: 1.不要让不同的代码同时执行。看。这里没有提到内存。它只是保证不同线程中的代码不会同时执行。 2. 在某些架构上它会插入缓存一致性指令。这迫使多处理器系统将数据刷新到实际内存中。但是你现在不应该担心这个案例 "a multiprocessor is cache consistent if all writes to the same memory location are performed in some sequential order" 3.插入内存屏障指令。它是给处理器的,告诉它不要打乱执行顺序。
此外,您的编译器也可能会阻止某些事情。因此,将您的变量声明为易变的。