acquire/release 语义真的足以实现关键部分吗?
Are acquire/release semantics really enough for implementing critical sections?
(这里,临界区,我的意思是任何同步机制,防止对某些资源的并发访问。)
似乎网络上的共识是进入临界区时获取语义,离开临界区时释放语义。但是这不是打开了死锁的可能性吗?
这里有一些伪代码来解释我的意思。原代码如下:
Thread 1:
enter A // acquire semantics
// ... some work within A
leave A // release semantics
enter B // acquire semantics
// ... some work within B
leave B // release semantics
Thread 2:
enter B // acquire semantics
// ... some work within B
leave B // release semantics
enter A // acquire semantics
// ... some work within A
leave A // release semantics
执行这段代码时,CPU 可以合法地将其转换成这样(获取前没有移动,发布后没有移动):
Thread 1:
enter A // acquire semantics
enter B // acquire semantics
// ... some work within A
// ... some work within B
leave A // release semantics
leave B // release semantics
Thread 2:
enter B // acquire semantics
enter A // acquire semantics
// ... some work within B
// ... some work within A
leave B // release semantics
leave A // release semantics
但是现在,我们遇到了以前没有的死锁危险!两个线程进入多个临界区,但顺序不同。
那么关键部分不需要防止 store/load 重新排序吗? IE。他们不需要顺序一致的语义而不仅仅是 acquire/release 吗?为什么没有指定
"moves" 对 acquire/release 的解释是一个有用的指南,但可能会失效,因为它描述了线程如何看待 其他线程 的操作。每个线程都必须将自己的操作视为按顺序发生。例如,线程 2 可以看到这个序列:
- 线程 1 获取 A
- 线程 2 获取 B
但随后线程 2 会将自己视为在获取 A 之前释放 B。相反,在相同的 运行 期间,线程 1 可以将其视为:
- 线程 2 获取 B
- 线程 1 获取 A
但随后线程 1 会将自己视为在获取 B 之前释放 A。
(这里,临界区,我的意思是任何同步机制,防止对某些资源的并发访问。)
似乎网络上的共识是进入临界区时获取语义,离开临界区时释放语义。但是这不是打开了死锁的可能性吗?
这里有一些伪代码来解释我的意思。原代码如下:
Thread 1:
enter A // acquire semantics
// ... some work within A
leave A // release semantics
enter B // acquire semantics
// ... some work within B
leave B // release semantics
Thread 2:
enter B // acquire semantics
// ... some work within B
leave B // release semantics
enter A // acquire semantics
// ... some work within A
leave A // release semantics
执行这段代码时,CPU 可以合法地将其转换成这样(获取前没有移动,发布后没有移动):
Thread 1:
enter A // acquire semantics
enter B // acquire semantics
// ... some work within A
// ... some work within B
leave A // release semantics
leave B // release semantics
Thread 2:
enter B // acquire semantics
enter A // acquire semantics
// ... some work within B
// ... some work within A
leave B // release semantics
leave A // release semantics
但是现在,我们遇到了以前没有的死锁危险!两个线程进入多个临界区,但顺序不同。
那么关键部分不需要防止 store/load 重新排序吗? IE。他们不需要顺序一致的语义而不仅仅是 acquire/release 吗?为什么没有指定
"moves" 对 acquire/release 的解释是一个有用的指南,但可能会失效,因为它描述了线程如何看待 其他线程 的操作。每个线程都必须将自己的操作视为按顺序发生。例如,线程 2 可以看到这个序列:
- 线程 1 获取 A
- 线程 2 获取 B
但随后线程 2 会将自己视为在获取 A 之前释放 B。相反,在相同的 运行 期间,线程 1 可以将其视为:
- 线程 2 获取 B
- 线程 1 获取 A
但随后线程 1 会将自己视为在获取 B 之前释放 A。