一般来说,“原子地与内存交换内存”对于CPU来说是一件不寻常的事情。(The MC68030 is notable as one of the few historical machines that did support it.)在大多数情况下,你只需要用一个互斥体来保护这两个对象。因此,如果你需要原子地删除一个锁,并使用另一个锁,你需要第三个锁来保护这对锁。 另一种选择是将锁表示为单个机器字中的不同位或位域(如果它们适合的话)。然后,您可以使用LL/SC对来原子地旋转您需要的它们的任何组合。但这是以更高的争用为代价的;现在,正在使用任何锁的所有线程都在竞争对同一字的访问。 一些体系结构提供双字LL/SC或比较和交换,这样你实际上可以使用两个相邻的机器字(对于无锁链表等也很有用),但似乎RISC-V没有。
2条答案
按热度按时间aurhwmvo1#
一般来说,“原子地与内存交换内存”对于CPU来说是一件不寻常的事情。(The MC68030 is notable as one of the few historical machines that did support it.)在大多数情况下,你只需要用一个互斥体来保护这两个对象。因此,如果你需要原子地删除一个锁,并使用另一个锁,你需要第三个锁来保护这对锁。
另一种选择是将锁表示为单个机器字中的不同位或位域(如果它们适合的话)。然后,您可以使用LL/SC对来原子地旋转您需要的它们的任何组合。但这是以更高的争用为代价的;现在,正在使用任何锁的所有线程都在竞争对同一字的访问。
一些体系结构提供双字LL/SC或比较和交换,这样你实际上可以使用两个相邻的机器字(对于无锁链表等也很有用),但似乎RISC-V没有。
j8ag8udp2#
@ErikEidt在评论中问了正确的问题,帮了我的忙:
如果另一个锁不可用,它应该怎么做?在你的情景中,拥有第一个锁是否以某种方式保证了第二个锁是可用的?
我已经想清楚了,要求这样的原子“释放然后获取”操作似乎是一件奇怪的事情。
如果第一个锁A保证第二个锁B可用:
acquire(B); release(A);
,其中acquire(B)
总是成功的。(死锁也不可能发生)如果它没有这样的保证,那么当B不可用时:
acquire(B); release(A);
相同。(可能存在死锁)release(A); acquire(B);
我最初的意图是使用此操作来解决由于在两个锁之间切换而导致的死锁问题。但似乎所有“release-then-acquire”操作将执行的操作都与作为两个单独操作的纯获取和释放操作相同。可能需要更多地考虑我的并发设计。:\