2017-03-13 37 views
0

有一天,我发现了关于并行线程互斥执行可能的错误一篇有趣的文章,随后进行讨论:pthreads互斥体实现中是否存在基本错误?

https://lwn.net/Articles/575460

我现在的并行线程库(和一般的多线程编程)的知识是太可怜了我理解大部分的讨论,但我必须承认这导致了一些令人不安的结论。这是否意味着当前pthreads mutex的实现确实存在严重缺陷,因此,Linux内核(无疑严重依赖于多线程代码)可能会涌现出来源于该缺陷的严重错误?我一直认为代码是基本的,低级的和基本的,像基本的同步原语,比如互斥体已经过彻底的测试(甚至被证明是正确的)。相反,我们突然发现大家多年来没有注意到的“特例”,包括Linus Torvalds在内的任何人都无法确定它在内核代码中可能出现的频率。 听起来很恐怖,不是吗?

无论如何,有什么问题和它(本文是从2013年末)可能的解决方案的现状如何?互斥体实施是否已更改为涵盖省略的特例?或者是否改变了库文档(POSIX标准?)以加强可以安全使用互斥体的条件?有没有做过任何事情?学习pthreads库是否有意义,如果它很可能是腐败和不可靠的?或者,我对这个问题的理解是错误的,根本没有问题?

+0

链接的讨论与POSIX互斥体无关。 POSIX互斥体是*用户空间*对象。讨论的内容是在* kernel *空间中运行的* kernel *锁。另外我怀疑基本错误不在内核锁中,它的使用方式是 - 释放锁之后释放内存,这意味着等待锁的第二个线程将获得锁,递增有问题的引用计数,然后尝试使用已释放的内存。 –

+0

@AndrewHenle Btw大多数互斥体(包括POSIX和C++ 11)明确允许该文章中描述的用法。 – Ivan

+0

@Ivan我不确定你的观点是什么。曾经发布的C,C++和POSIX标准的每个版本都无法防止出错代码。你读过整篇文章了吗?使用位于该内存中的锁来保护任何内存几乎是不可能的,无论该锁是POSIX互斥锁,Linux内核锁还是C++ 11互斥锁。这种内存在锁定期间不能被释放,并且有***无法阻止另一个线程等待获取线程在释放锁定后释放的锁定。这是一个错误。 –

回答

0

P线程是POSIX线程和值得了解独立任何特定的实现。 Linux不是唯一的。 Pthreads已经过尝试和测试,即使在那里也能很好地工作。

如果你读了文章仔细问题只体现在某些情况下。只有在锁座唤醒第三根线,并且等待锁的时刻,您必须让一根线等待获取锁。此外,其不安全的原因在于,“旋转”线程的行为会导致第三个线程出现问题,因为它认为可以安全地释放包含互斥体的对象,当第三个线程将不会使用它时。

其实这个问题是不是互斥的实现在所有,而不是这么多它是如何被使用的,但肯定的修复,使其安全地使用这种方式会受到欢迎。 这似乎是内核社区关心的问题,因为这个问题可能表现在相当广泛的编码模式中(即参考计数来决定何时可以安全删除)。 如果您有兴趣,您可以检查内核更改历史记录以查看是否有内存更改历史记录。

免责声明:我只是在外围熟悉这些问题。更熟悉互斥体实现和内核的人可能会更好地指导您。

0

对于POSIX和C++ 11互斥锁,该文章中显示的互斥锁使用有效。 Glibc有类似的bug,现在已经修复。

我认为每一个同步glibc中原始有类似的错误在一些点。这里是一些(现在都固定):在并行线程障碍

  • Bug 12674

    • Bug 13065竞争条件 - sem_post/sem_wait比赛造成sem_post返回EINVAL

    我不知道什么是它的状态现在,但很可能至少共享的POSIX primites不完全符合。

    Musl libc试图提供POSIX原语的正确实现。这就是为什么pthread_barrier_wait共享屏障共享全局进程内锁与MAP_FIXEDmmap调用。而且我不确定这是否能解决所有问题。很高兴知道glibc如何处理这个问题,很可能它不会,所以这可能是一个“基本错误”的例子。

    您可能想检查musl作者的个人资料 - Rich Felker - 和他的问题列表在这里找到许多问题。