4

假设线程 1尝试使用该语句获取lockObj对象上的锁lock(lockObj),但在线程 1 尝试获取该对象上的锁时,该对象已被线程 2锁定。线程 1 会阻塞,对吗?

现在假设在这个阻塞期间,有一个上下文切换,因为还有其他线程和应用程序等待运行。线程 1 再次处于运行状态并能够获取锁之前的经过时间是否取决于操作系统计时器分辨率(例如:Windows 7 上的默认 15.6 毫秒)?

如果上述问题的答案是肯定的,那么我还有一个疑问:

很容易创建一个简单的程序来测试Thread.Sleep(1)使用Stopwatch的平均开销,并得出结论它收敛到 OS 计时器分辨率(例如 15.6 毫秒)。但是我发现很难创建一个程序来为lock语句获得相同的结论。主要是因为:

1)很难保证试图获取锁的线程会一直阻塞(或者至少要在获取锁之前知道自己何时阻塞);

2)每当线程试图获取锁块时,我不知道如何强制进行上下文切换。当前运行的线程阻塞时是否总是有上下文切换?

任何帮助将不胜感激。

4

1 回答 1

0

假设线程 1 尝试使用 lock(lockObj) 语句获取 lockObj 对象的锁,但在线程 1 尝试获取该对象的锁时,该对象已被线程 2 锁定。线程 1 会阻塞,对吗?

是的。

现在假设在这个阻塞期间,有一个上下文切换,因为还有其他线程和应用程序等待运行。线程 1 再次处于运行状态并能够获取锁之前的经过时间是否取决于操作系统计时器分辨率(例如:Windows 7 上的默认 15.6 毫秒)?

不直接,不。通常,线程 1 将在它被阻塞的等待对象发出信号后立即准备就绪。届时,操作系统调度算法将运行,并且线程 1 将设置为在一个核心上运行,如果一个核心是空闲的或者如果它的优先级足以允许它包含在线程集中以在可用核心上运行。有可能一个定时器中断了我偶然到达并设置另一个高优先级的“线程 3”准备好,从而阻止线程 1 运行,但这与说“获取锁取决于操作系统定时器分辨率”相去甚远.

如果有一个内核可以自由运行线程 1,我凭经验发现它在我的 Windows 系统上的线程 2 发出信号后运行约 7 微秒——几微秒,而不是 15.6 毫秒或类似的时间。

如果线程 1 必须等到下一个定时器中断在某个信号后运行,性能将非常糟糕。它不需要等待 - 来自线程 2 的信号已进入操作系统,操作系统决定当时运行哪组线程。它可能不会立即运行线程 1,因为所有内核都已经在运行更高优先级的线程,它可能会抢占线程 2,因为线程 1 具有更高的动态优先级,或者它可能会通过向另一个内核发出硬件中断来抢占在另一个内核上运行的另一个线程内核使用其处理器间通信驱动程序。计时器中断和“量子”事物在您的场景中基本上是无关紧要的。

尽量不要专注于“量子”概念(这是一个愚蠢的名字,因为“量子”应该是不可分割的,并且由于 I/O 和线程间信号,线程很少以精确的计时器驱动间隔运行),并思考而不是一个状态机,它的输入是硬件中断和系统调用,输出是一组在内核上运行的线程。硬件定时器中断只是可以改变运行线程集的输入之一。

于 2014-09-14T05:14:17.227 回答