C读和线程安全(linux)

如果在同一个文件描述符(让我们感兴趣的是一个本地文件,它是一个套接字文件描述符)中调用两个不同的线程中的read (或write ,或两者),将会发生什么情况,而不使用显式的同步机制?

读和写是系统调用,因此,在单核CPU上,两个读操作可能同时执行可能是不吉利的。 但是,多核心…

Linux内核将会做什么?

让我们来更一般一点:其他内核(如BSD)的行为总是一样的吗?

编辑:根据closures的文档 ,我们应该确保该文件描述符不被其他线程中的系统调用使用。 因此,在closures一个文件描述符之前,需要明确的同步(如果线程可能调用它仍然在运行,那么还需要读/写)。

Solutions Collecting From Web of "C读和线程安全(linux)"

任何系统级(syscall)文件描述符访问在所有主流的类UNIX操作系统中都是线程安全的。 虽然取决于年龄,但他们不一定是信号安全的。

如果您从两个不同的任务调用readwriteaccept或相似的文件描述符,则内核的内部锁定机制将解决争用。

对于读取,每个字节可能只能读取一次,写入将以任何未定义的顺序进行。

stdio库函数freadfwrite和co。 在控制结构上也有默认的内部锁定,但是通过使用标志可以禁用该功能。

关于关闭的注释是因为在任何其他线程试图使用它的情况下,关闭文件描述符并没有什么意义。 所以就内核而言,尽管是“安全的”,但却可能导致奇怪的,难以诊断的情况。

如果一个线程关闭一个文件描述符而另一个线程正在尝试读取它,则第二个线程可能会收到意外的EBADF错误。 更糟糕的是,如果第三个线程同时打开一个新文件,可能会重新分配相同的fd,第二个线程可能会意外地从新文件中读取,而不是预期的文件。

照顾那些追随你的脚步的人

用互斥量信号保护文件描述符是完全正常的。 它消除了对内核行为的任何依赖,所以你的消息边界现在是确定的。 然后你不必引用最后一段在15,489行的manpage的底部,这就解释了为什么互斥是没有必要的(我夸大了,但你明白了我的意思)

这也使任何读取你的代码的人都清楚,文件描述符被多个线程使用。

附加福利

以这种方式使用互斥体有附加益处。 假设你有不同的消息来自不同的线程,其中一些消息比其他消息更重要。 所有你需要做的就是设置线程的优先级,以反映他们的消息的重要性。 这样,操作系统将确保您的邮件将按照重要性的顺序发送,为您尽可能少的努力。

结果将取决于线程如何计划在特定时刻运行。

一种可能避免多线程未定义行为的方法是假设你正在执行内存操作。 例如更新链表或更改变量等

如果您使用互斥/信号/锁定或其他一些同步机制,它应该按预期工作。