C++ 使用多线程在GNUC中使用写函数安全吗

C++ 使用多线程在GNUC中使用写函数安全吗,c++,multithreading,sockets,gcc,redhat,C++,Multithreading,Sockets,Gcc,Redhat,将多个线程的函数调用写入同一套接字 安全吗? 我们想在它们之间添加同步吗? 它会不会引起像这样的问题 应用程序从网络层到应用程序层的写入/读取延迟 我们正在使用 GNU C++库 Linux Redhat环境下的GCC4 这是一个服务器端流程,其中服务器和客户端之间只有一个套接字连接服务器和客户端位于两台不同的机器上数据从服务器发送到客户端到服务器 问题1—当服务器向客户端发送数据时(多个线程通过同一个套接字向客户端写入数据),但从某些线程写入的数据没有发送到客户端,甚至没有发送到同一台机器的网

将多个线程的函数调用写入同一套接字

安全吗? 我们想在它们之间添加同步吗? 它会不会引起像这样的问题 应用程序从网络层到应用程序层的写入/读取延迟

我们正在使用 GNU C++库 Linux Redhat环境下的GCC4

这是一个服务器端流程,其中服务器和客户端之间只有一个套接字连接服务器和客户端位于两台不同的机器上数据从服务器发送到客户端到服务器

问题1—当服务器向客户端发送数据时(多个线程通过同一个套接字向客户端写入数据),但从某些线程写入的数据没有发送到客户端,甚至没有发送到同一台机器的网络层(Tcpdump没有该数据)

问题2—当客户端向服务器发送数据时,客户端发送的数据显示在服务器应用程序的TCPdump中,该服务器应用程序未收到该服务器应用程序的TCPdump,该服务器应用程序正在使用循环中的“读取”和“选择”函数从单线程的套接字读取数据


我们无法确定发生这些问题的模式,我们认为这是在这么多线程向同一套接字写入时发生的。我们没有同步写入函数,希望操作系统正在处理同步操作。从多个线程使用write()是不安全的。无法保证输出不会被混合在一起。一次写入可以将其一半字节放入套接字,然后另一次写入可以开始将其放入字节。如果您需要确保每次写入都是连续写入的(很难想象不需要这种保证),那么您需要一个锁或其他同步方法。

write()是一个系统调用,而不是库函数,而且系统调用通常保证是原子的。

未指定哪个
写入
调用首先完成。上下文开关可以在第一条指令中暂停两个写入中的任何一个。这可能导致任意排序。没有任何
write
,内核也无法做到这一点。这是一个根本问题


您的数据将以未指定的顺序写入,这可能是您无法接受的。

从程序格式良好的意义上讲,这是“安全的”,但您在套接字上看到的结果可能不是您所期望的。@KerrekSB:这是一个奇怪的评论。任何线程不安全的程序都可以在这个意义上被称为“安全的”,不是吗?@NedBatchelder:当然不是。例如,依赖静态缓冲区来保持其内部状态的函数根本不是线程安全的,同时多次调用它的程序只是定义不清。相反,同时调用
write
的程序并不是自动定义错误的。可能重复的@samira的可能重复:它肯定会导致您描述的问题,但无法确定同步是否是原因。在访问函数时,您可以使用互斥锁,以便一次只有一个线程访问该函数……没有互斥锁是否会导致读取问题?有时在6分钟后tcpdump上可以看到写入的数据,我认为这是不对的。write()是一个系统调用,而不是库函数,系统调用通常保证是原子的。我从来没有见过有人说write()不是原子的。@EJP:你应该把它作为另一个答案来写。对,不对。系统调用保证是原子的(从某种意义上说是“安全的”,它既不会崩溃也不会损坏您的数据),但不能保证由两个线程同时提交(原子地)的数据是原子地传输的:。还要注意的是,从技术上讲,
write
send
可以写得比您要求的少,在这种情况下,您必须继续第二次写操作,无论如何都会丧失所有原子性。