C 只有当所有相关线程在使用资源之前尝试获取它们应该获取的锁时,互斥锁才能正常工作吗?

C 只有当所有相关线程在使用资源之前尝试获取它们应该获取的锁时,互斥锁才能正常工作吗?,c,multithreading,kernel,mutex,C,Multithreading,Kernel,Mutex,在第一次参加操作系统课程之前,我只是第一次学习锁。我最初认为锁会字面上“锁定某些资源”,您需要在其中指定资源(可能通过指向内存中资源地址的指针),但在阅读了几个真正基本的自旋锁实现(例如,类unix的培训OS“xv6”版本)之后: 以及前面的堆栈溢出问题:() 我想我全错了 相反,在我看来,锁实际上只是一个类似布尔标志的变量,它暂时(或无限期)阻止某些代码的执行,这些代码将利用资源,但只有在另一个线程实际也尝试获取锁的情况下才会执行(其中,在试图获取锁的第二个线程中,第二个线程的阻塞具有副作

在第一次参加操作系统课程之前,我只是第一次学习锁。我最初认为锁会字面上“锁定某些资源”,您需要在其中指定资源(可能通过指向内存中资源地址的指针),但在阅读了几个真正基本的自旋锁实现(例如,类unix的培训OS“xv6”版本)之后:

以及前面的堆栈溢出问题:()

我想我全错了

相反,在我看来,锁实际上只是一个类似布尔标志的变量,它暂时(或无限期)阻止某些代码的执行,这些代码将利用资源,但只有在另一个线程实际也尝试获取锁的情况下才会执行(其中,在试图获取锁的第二个线程中,第二个线程的阻塞具有副作用,即在第一个线程释放锁之前,该第二个线程无法利用资源)因此,现在我想知道:如果一个设计糟糕的线程没有使用互斥锁,只是试图利用另一个设计良好的线程锁定的资源,那么设计糟糕的线程是否能够访问该资源(通过简单地忽略互斥体——我现在认为它是线程应该看到的标志,但有机会忽略)

如果是这样的话,那么为什么我们要将锁实现为复杂的布尔变量,以便所有线程都必须使用锁,而不是阻止访问内存区域的锁

由于我对所有这些都比较陌生,如果我的问题和答案陈述不正确,我非常感谢任何合理的术语编辑建议

多谢各位

--编辑,谢谢大家的提示和帮助

如果是这样的话,那么为什么我们要将锁实现为复杂的布尔变量,以便所有线程都必须使用锁,而不是阻止访问内存区域的锁

原因很多:

  • 如果控制访问的对象不是内存区域怎么办?如果是文件或网络连接怎么办

  • 编译器如何知道何时访问受保护的内存区域?编译器是否必须假设任何地方的内存访问都可能与其他线程同步?这将导致许多优化不可能,包括在寄存器中存储可能共享的变量,这一点非常关键

  • <> LI> < P>硬件是否需要在任何粒度上支持锁定内存?它如何知道内存与对象相关联?考虑链接列表。是否需要锁定与该链表关联的所有内存和其中的每个对象?当从列表中添加或删除对象时,是否必须更改哪些内存是保护的?ed?那不是既昂贵又极难使用吗

  • 它如何知道何时释放锁?假设您访问某个需要保护的内存区域,然后再访问另一个内存区域。实现如何知道在这两次访问之间是否允许其他线程访问该区域?实现需要知道访问hat region在这两次访问中是否依赖于共享状态的一致视图。它怎么知道?通过保持锁而出错,并发性受到影响。通过在两次访问之间释放锁而出错,代码的行为可能不可预测

  • 等等

    如果是这样的话,那么为什么我们要将锁实现为复杂的布尔变量,以便所有线程都必须使用锁,而不是阻止访问内存区域的锁

    原因很多:

  • 如果控制访问的对象不是内存区域怎么办?如果是文件或网络连接怎么办

  • 编译器如何知道何时访问受保护的内存区域?编译器是否必须假设任何地方的内存访问都可能与其他线程同步?这将导致许多优化不可能,包括在寄存器中存储可能共享的变量,这一点非常关键

  • <> LI> < P>硬件是否需要在任何粒度上支持锁定内存?它如何知道内存与对象相关联?考虑链接列表。是否需要锁定与该链表关联的所有内存和其中的每个对象?当从列表中添加或删除对象时,是否必须更改哪些内存是保护的?ed?那不是既昂贵又极难使用吗

  • 它如何知道何时释放锁?假设您访问某个需要保护的内存区域,然后再访问另一个内存区域。实现如何知道在这两次访问之间是否允许其他线程访问该区域?实现需要知道访问hat region在这两次访问中是否依赖于共享状态的一致视图。它怎么知道?通过保持锁而出错,并发性受到影响。通过在两次访问之间释放锁而出错,代码的行为可能不可预测


  • 诸如此类。

    您对所有线程都应该正确实现对共享资源的访问的理解是正确的。而且没有“锁会阻止对内存区域的访问”——这需要特殊的硬件支持。这种现象以前已经观察到。Paul McKenney称为RCU“通过社会工程进行同步”,并指出锁需要所有调用者同样的努力来锁定互斥锁。更现代