【问题标题】:Using fetch-and-add as lock使用 fetch-and-add 作为锁
【发布时间】:2020-06-11 07:53:18
【问题描述】:

我试图了解如何将 fetch-and-add 用作锁。以下是这本书(操作系统:3 个简单的部分)所说的:

基本操作非常简单:当 一个线程希望获得一个锁,它首先进行原子获取和添加 关于门票价值;该值现在被认为是该线程的“转” (轮到我了)。然后使用全局共享的 lock->turn 来确定 轮到哪个线程了;当 (myturn == turn) 对于给定的线程, 轮到该线程进入临界区了。

我不明白的是线程如何在进入临界区之前检查另一个进程是否持有锁。我只能读到值将增加,没有提到检查!

另一部分说:

解锁完成 只需增加轮次,使得下一个等待线程(如果 有一个)现在可以进入临界区了。

我不能以不执行检查的方式来解释,这不可能是真的,因为它包含了锁定关键部分的全部目的。我在这里想念什么?谢谢。

【问题讨论】:

    标签: multithreading x86 operating-system locking mutual-exclusion


    【解决方案1】:

    我不明白的是线程如何在进入临界区之前检查锁是否被另一个进程持有。

    为此,您需要一个“原子提取”,可能类似于“while( atomic_fetch(currently_serving) != my_ticket) { /* wait */ }”。

    如果您有“原子提取并添加”,那么您可以通过执行“原子提取并添加零值”来实现“原子提取”,可能类似于“while( atomic_fetch_and_add(currently_serving, 0) != my_ticket) { /* wait */ }”。

    供参考;完整的序列可能是这样的:

        my_ticket = atomic_fetch_and_add(ticket_counter, 1);
    
        while( atomic_fetch_and_add(currently_serving, 0) != my_ticket) {
            /* wait */
        }
    
        /* Critical section (lock successfully acquired). */
    
        atomic_fetch_and_add(currently_serving, 1);   /* Release the lock */
    

    当然,您可以使用更好的原子提取来代替(例如,对于某些 CPU,任何正常对齐的负载都是原子的)。

    【讨论】:

    • 非常感谢,这澄清了我发现的所有神秘事物。书上没有提到可以给它参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-04
    • 2013-07-30
    • 2022-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多