想象一下,您正在多核系统中使用Parallelism。
是否可以同时执行相同的指令?
请使用以下代码:
int i = 0;
if( blockingCondition )
{
lock( objLock )
{
i++;
}
}
在我看来,似乎在具有多个内核和并行性的系统上很可能在同一时刻检查blockingCondition,导致同时尝试锁定,依此类推。这是真的吗?
如果是这样,您如何确保跨处理器同步?
此外,.net TPL是否处理此类同步?其他语言怎么样?
修改 请注意,这是关于线程的不,但是任务和并行处理。
编辑2 好的,谢谢大家的信息。那么操作系统是否会确保写入内存是序列化的,确保通过易失性读取实现多核同步?
答案 0 :(得分:2)
要了解其工作原理,请记住:
锁定锁定(即递增a 锁定对象上的信号量)是一个 阻止对象的操作 已被锁定。
lock
的两个步骤,a)检查锁定
信号量是免费的,b)实际上
锁定对象,执行
'同时' - 即他们是
单片或原子操作
远与CPU和CPU之间的关系
关注记忆。
因此,您可以看到,如果2个线程进入您的if
- 块,则两个线程中的一个将获取锁定,另一个将阻塞,直到第一个线程完成if
。
答案 1 :(得分:1)
您关注的正是为什么我们需要像lock
这样的特殊机制,而不能简单地使用布尔标志。
“同时”问题的解决方案是lock
(调用Monitor.Enter()
)使用的算法。它涉及内存障碍和非常低级内存机制的知识,以确保没有2个线程可以同时获取锁。
注意:我只谈论.NET,而不是Java。
答案 2 :(得分:1)
这里描述的锁是objLock上的“Monitor”样式锁。正如您所指出的,在多核系统下,完全可以同时对开始进行两次“锁定”调用。但是,任何使用监视器的高级应用程序环境都会将监视器转换为semaphore请求(或者,根据您的操作系统和语言细节,互斥请求)在编译的字节代码中。
信号量在操作系统和/或硬件级别实现,更高级别的语言绑定到它们。在操作系统级别,它们被“保证”为原子级。也就是说,任何获取信号量的程序都保证是在那个时间点唯一这样做的程序。如果两个程序或程序中的两个线程同时尝试获取锁定,则会先进行(并成功),另一个进入第二个(并失败)。
此时,“如何确保同步”不再是应用程序员担心的问题,并且开始成为操作系统设计人员和硬件设计人员的问题。
它的结果是,作为一个应用程序编码器,你可以安全地假设“lock(objLock)”将是一个原子调用,无论你插入系统多少CPU。