有帮助吗?

解决方案

您的文章描述的内容现在已经普遍使用。大多数情况下,它被称为“关键部分 ;它包含一个互锁变量,一堆标志和一个内部同步对象(Mutex,如果我没记错的话)。通常,在几乎没有争用的场景中,Critical Section完全在用户模式下执行,而不涉及内核同步对象。这保证了快速执行。当争用很高时,内核对象用于等待,这会释放时间片导电,以便更快地进行周转。

通常,在这个时代实现同步原语的意义非常小。操作系统附带了大量此类对象,并且它们在比单个程序员可以想象的更广泛的场景中进行了优化和测试。实际上,需要花费数年的时间来发明,实现和测试良好的同步机制。这并不是说尝试没有价值:)

其他提示

Java的 AbstractQueuedSynchronizer (及其兄弟 AbstractQueuedLongSynchronizer )的工作方式类似,或者至少它可以类似地实现。这些类型构成了Java库中几个并发原语的基础,例如 ReentrantLock FutureTask

它通过使用原子整数来表示状态。锁可以将值0定义为已解锁,将1定义为已锁定。任何希望获取锁的线程都会尝试通过原子 compare-and-set 操作将锁定状态从0更改为1;如果尝试失败,则当前状态不为0,这意味着该锁由其他某个线程拥有。

AbstractQueuedSynchronizer 还通过维护 CLH队列来帮助等待锁定和条件的通知,这些是表示线路的无锁链接列表。等待获取锁定或通过条件接收通知的线程。这样的通知将等待条件的一个或所有线程移动到等待获取相关锁的队列的头部。

这个机器的大多数可以用表示状态的原子整数以及每个等待队列的几个原子指针来实现。实际调度哪些线程将争用检查和更改状态变量(例如,通过 AbstractQueuedSynchronizer#tryAcquire(int) )超出了这样一个库的范围并落到主机系统的调度器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top