主题:如果你只是在被阻止时准备就绪,你怎么能表示你准备好了?

时间:2018-03-16 23:50:31

标签: c multithreading

我的情况如下:在C中,我启动pthread,最终通过调用接收函数来阻止等待输入。它希望收到的数据基本上是一个回应。

回到我原来的执行线程,我想等到启动的线程准备好处理响应,然后我才能做任何可能导致响应的响应。我不希望在启动的线程能够接收它之前使响应到达。

编辑:原始线程发送UDP数据包。它不知道另一端是否存在 - 它试图了解另一端。它根据启动的线程是否在某个超时时间内收到响应来得出自己的结论。

我遇到的一个问题是启动的线程只有在被阻止时才真正准备就绪。它在调用阻塞接收函数之前给出的任何信号可能在它实际准备好之前就已经过了很长时间。考虑到你只是在被阻挡时准备就绪,你如何在准备好时发出信号?

现在我sleep()收到就绪信号,我知道这不是保证,也有缺点。

我遇到的另一个问题是,信号可以简单到将0更改为1而没有任何互斥保护吗?我读到ints are not atomic。但我只想知道int何时停止0,而且这个int只会从0变为0以外的其他内容。

2 个答案:

答案 0 :(得分:1)

回答实际问题

内核的网络缓冲完全解决了您的真正问题。一旦你有一个由socket创建并使用bind绑定到本地端口的UDP套接字,那么内核将把缓冲区中的传入流量保存到该端口,直到你调用recv个函数之一为止

因此,在调用recv时无需仔细同步。

提问的问题

Go / Golang及其异步goroutines之类的东西阻塞了线程池中的调用。所以goroutine执行阻塞任务,然后切换到另一个线程上的另一个goroutine。当一些CPU被阻塞时,它会创建更多线程来完全使用所有CPU。

如果有兴趣,请查看Go1.4 src/runtime/proc.csrc/syscall/asm_linux_amd64.s

为了表示您的线程处于阻塞系统调用中,您必须在进入系统调用之前对标志进行原子写入。在标志写入和系统调用之间切换上下文的可能性非常小,必须完美处理,但这种可能性很小。

请注意,原子写入。不是信号量或互斥量,它们更复杂,可能会被打断。

答案 1 :(得分:1)

@bnaecker在评论中说道,加上听起来有点令人困惑的设计。

如果某些东西需要发送请求并等待响应,那么如果一个'tx / rx'线程同时执行这两个操作,则最简单。那么,你可以将一个组合请求/响应结构(以及指向一个的指针)排队到tx / rx线程(生产者 - 消费者队列)吗?然后它可以发送请求,顺序接收响应并填写结构的响应位。如何将完成的请求/响应结构传回给其创建者取决于您和您的整体设计。对于同步接口,您可以在发起方等待的请求/响应结构中发送信号量或condvar - tx / rx线程在填充响应时发出信号(或错误消息:)。对于异步,您可以将r / r结构指针重新排列在另一个生产者 - 消费者队列上。

对于“最终”灵活性,r / r结构可以包含指向发起者设置的完成例程的函数指针。 tx / rx线程使用r / r结构指针作为参数调用完成例程。然后,完成例程可以执行发起者所需的任何操作 - 发出一些condvar信号,排队结构,将结构发布到某个GUI输入队列,无论如何。