3

想象一下,您正在多核系统中使用并行。

相同的指令不能同时执行吗?

采取以下代码:

int i = 0;

if( blockingCondition )
{
  lock( objLock )
  {
    i++;
  }
}

在我的脑海中,似乎很有可能在具有多核和并行性的系统上,blockingCondition 可以在同一时刻被检查,导致同时尝试锁定,等等......这是真的?

如果是这样,您如何确保跨处理器的同步?

此外,.net TPL 是否处理这种类型的同步?其他语言呢?

编辑 请注意,这不是关于线程,而是关于任务和并行处理。

编辑 2 好的,谢谢大家的信息。那么操作系统是否会确保对内存的写入是序列化的,通过易失性读取确保多核同步?

4

3 回答 3

2

要了解为什么会这样,请记住:

  1. 锁定一个锁(即在对象上增加一个锁信号量)是一个在对象已经被锁定时阻塞的操作。

  2. locka) 检查锁信号量是否空闲,b) 和实际锁定对象 这两个步骤是“同时”执行的 - 即,就 CPU 和内存之间的关系而言,它们是单片或原子操作。

因此,您可以看到,如果有 2 个线程进入您的if-block,则两个线程中的一个将获取锁,另一个将阻塞,直到第一个线程完成if.

于 2010-10-10T11:02:20.397 回答
1

您所关心的正是为什么我们需要一种特殊的机制,例如lock并且不能简单地使用布尔标志。

您的“同时”问题的解决方案在于lock(调用Monitor.Enter())使用的算法。它涉及内存屏障和非常低级内存机制的知识,以确保没有 2 个线程可以同时获取锁。

注意:我说的只是 .NET,而不是 Java。

于 2010-10-10T11:10:59.490 回答
1

像您在此处描述的锁是 objLock 上的“监视器”样式锁。正如您所指出的,在多核系统下,两个“锁定”调用完全有可能同时开始。但是,任何使用监视器的高级应用程序环境都会将监视器转换为编译字节码中的信号量请求(或者,取决于您的操作系统和语言细节,互斥请求)。

信号量在操作系统和/或硬件级别实现,更高级别的语言绑定到它们。在操作系统级别,它们“保证”是原子的。也就是说,任何获取信号量的程序都保证在那个时间点是唯一这样做的。如果两个程序,或者一个程序中的两个线程同时尝试获取锁,一个会先去(并且成功),另一个会去第二(并且失败)。

此时,“如何确保同步”不再是应用程序员担心的问题,而是开始成为操作系统设计人员和硬件设计人员的问题。

其结果是,作为应用程序编码人员,您可以放心地假设“lock(objLock)”将是一个原子调用,无论您在系统中插入多少 CPU。

于 2010-10-10T11:16:33.560 回答