11

这听起来像是一个愚蠢的问题,但如果一个人在多线程应用程序中锁定了一个资源,那么在资源上发生的操作,是原子完成的吗?

IE:处理器是否会被中断,或者当该资源被锁定时是否会发生上下文切换?如果是这样,那么在它被安排回来完成它的进程之前,没有其他东西可以访问这个资源。听起来像是一项昂贵的手术。

4

4 回答 4

16

处理器肯定仍然可以切换到另一个线程,是的。事实上,在大多数现代计算机中,无论​​如何都可以同时运行多个线程。锁定只是确保没有其他线程可以获取相同的锁,因此您可以确保对该资源的操作在该资源方面是原子的。使用其他资源的代码可以完全独立运行。

您通常应该尽可能锁定短操作。您还可以选择锁的粒度...例如,如果您在共享对象中有两个独立变量,则可以使用两个单独的锁来保护对这些变量的访问。这可能会提供更好的并发性——但同时,更多的锁意味着更多的复杂性和更多的死锁可能性。在并发方面总是有一个平衡的行为。

于 2010-02-06T17:15:31.433 回答
7

你完全正确。这就是为什么在短时间内锁定如此重要的原因之一。然而,这并不像听起来那么糟糕,因为在持有锁的线程释放它之前,没有其他正在等待锁的线程被调度。

于 2010-02-06T17:16:22.037 回答
2

是的,上下文切换肯定会发生。这就是为什么在访问共享资源时,从另一个线程中锁定它也很重要。当线程 A 拥有锁时,线程 B 无法访问锁定的代码。

例如,如果两个线程运行以下代码:

1. lock(l);
2. -- change shared resource S here --
3. unlock(l);

在步骤 1 之后可能会发生上下文切换,但此时其他线程无法持有锁,因此无法更改共享资源。如果在没有锁的情况下访问其中一个线程上的共享资源 - 可能会发生坏事!

关于浪费,是的,这是一种浪费的方法。这就是为什么有些方法试图完全避免锁定。这些方法被称为无锁,其中一些基于强锁定服务,例如CAS(Compare-And-Swap)或其他。

于 2010-02-06T17:25:23.860 回答
0

不,它并不昂贵。通常只有两种可能:

1)系统还有其他可以做的事情:在这种情况下,系统仍在使用所有可用内核做有用的工作。

2)系统无事可做:这种情况下,持有锁的线程将被调度。一个健全的系统不会让一个核心闲置,而有一个未安排的准备运行的线程。

So, how can it be expensive? If there's nothing else for the system to do that doesn't require acquiring that lock (or not enough other things to occupy all cores) and the thread holding the lock is not ready-to-run. So that's the case you have to avoid, and the context switch or pre-empt issue doesn't matter (since the thread would be ready-to-run).

于 2011-09-17T16:10:22.470 回答