posix C write()和线程安全

时间:2011-01-04 09:43:47

标签: c thread-safety posix

有一种方法可以序列化C write(),这样我就可以在套接字上写字节,在k线程之间共享,没有数据丢失?我想这个问题的解决方案包括用户空间锁定,以及可扩展性如何?提前谢谢。

3 个答案:

答案 0 :(得分:4)

我认为正确的答案取决于您的线程是否需要同步等待响应。如果他们只需要向套接字写一些消息而不是等待对等体做出响应,我认为最好的答案是让一个专用于从其他线程发送消息的队列中写入消息的线程。这样,工作线程可以简单地将他们的消息放在队列上,继续做其他事情。

当然,队列必须受到互斥锁的保护,但任何一个线程只需要在操作队列时保持锁定(保证很短的时间)。让每个线程直接写入套接字的更明显的替代方案是每个线程都要保持锁定,只要它完成写操作。这总是比仅仅将一个项目添加到队列要长得多,因为写入是系统调用,并且可能会长时间阻塞。

即使你的线程需要对他们的消息做出响应,它仍然可能需要做类似的事情。您的套接字服务线程变得更加复杂,因为您必须在套接字上执行类似select()的操作以进行读取和写入以阻止阻塞,并且您还需要一种方法来将消息与响应和方式进行匹配在他们的回复到达时通知主题。

答案 1 :(得分:0)

由于POSIX似乎没有在send(2)上指定原子性保证,因此您可能必须使用互斥锁。当然,这种序列化可以降低可扩展性。

答案 2 :(得分:0)

一种可能的方法是使用锁定机制。每个线程都应该等待锁定,然后才能在套接字上写入任何内容,并且一旦完成就应该释放锁定。 如果所有线程都发送完全相同类型的消息,接收方端在读取数据时不会有任何问题,但如果不同的线程可以发送具有不同信息的不同类型的数据,则应该有一个唯一的消息ID关联使用每种数据并最好发送线程ID(尽管没有必要,但可能会帮助您调试小问题)。

您可以拥有如下结构:

typedef struct my_socket_data_st
{
int msg_id;
#ifdef __debug_build__
    int thread_id;
#endif
size_t data_size_in_bytes;
.... Followed by your data ....
} my_socket_data_t

可伸缩性取决于很多东西,包括运行应用程序的硬件资源。由于它是网络应用程序,因此您还必须考虑网络带宽。虽然没有(有一些,但我认为你现在可以忽略它们用于你的应用)操作系统通过套接字发送/接收数据的限制,但你必须考虑使send同步或根据您的要求异步。此外,由于您正在锁定,您还必须考虑锁定拥塞。如果其他线程无法轻松获得锁定,则会导致性能下降。