获取/发布语义确实足以实现关键部分吗?

时间:2018-11-02 09:21:33

标签: multithreading locking deadlock memory-barriers

(在这里,通过关键部分,我的意思是任何同步机制,可防止同时访问某些资源。)

似乎在网络上的共识是,您只需要在进入关键部分时获取语义,并在离开关键部分时释放语义。但这难道没有带来僵局的可能性吗?

这里有一些伪代码来解释我的意思。这是原始代码:

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

但是现在,我们面临着前所未有的僵局危险!两个线程进入一个以上的关键部分,但顺序不同。

所以关键部分也不需要防止存储/装载重新排序吗?即他们不是需要顺序一致的语义,而不仅仅是获取/发布吗?为什么未指定

1 个答案:

答案 0 :(得分:1)

“获取/释放”的“动作”解释是有用的指南,但由于它描述了线程如何看待其他线程的动作,因此可能会分解。每个线程必须将自己的操作视为按顺序进行。例如,线程2可以看到以下顺序:

  1. 线程1获得A
  2. 线程2获得B

但是随后线程2在获取A之前将自己视为释放B。相反,在同一运行期间,线程1可能将其视为:

  1. 线程2获得B
  2. 线程1获得A

,但是随后线程1将自己视为在获取B之前释放A。