这是在Linux上,但理想情况下,我想要一个符合POSIX的解决方案。
我有两个线程,每个线程都可以通过API函数写入硬件总线。在任何给定时间只允许一个线程写入总线,并且在总线写入之后,在几百毫秒量级的给定时间内不得写入总线。
这两个线程都实现为状态机。
显而易见的解决方案是使用互斥锁来序列化对总线的访问,设置计数器或时间戳,并在适当的时间到期后让状态机解锁互斥锁。
这对我来说似乎有点脆弱。如果将来的维护开发人员错误地修改了状态机,互斥锁可能不会被释放,从而导致难以诊断的死锁。
有没有一个API调用可以锁定一个互斥锁,但在给定的超时后自动解锁?谷歌揭示了pthread_mutex_timedlock(),但这并不完全是一回事。
发布于 2013-01-18 19:54:45
我不知道有任何pthreads允许自动释放锁。
就我个人而言,我会尝试通过单个线程来序列化对总线的访问,以避免这些复杂性。如果该线程维护一个输入队列,而其他线程将它们的请求发送给它,那么它可以执行任何它想要的序列化和冲突解决,这也使得在进一步访问之前实现延迟变得更容易。只要小心不要在这个线程中使用任何阻塞函数,您唯一真正失败的情况就是它可能会被意外终止。
如果需要从总线读取和写入,可以为每个线程提供一个输入队列,并让工作线程向IO线程发送一个“读请求”,然后等待响应被发送回它自己的输入队列。如果一个线程只有一个未完成的请求,那么你实际上不需要一个队列,一个简单的condition variable和一个指向结构的指针就可以了。
如果您确实希望两个线程共享资源,那么我认为您总是会有互斥锁被锁定的风险。即使您设置了计时器并在固定时间后强制释放互斥锁,这也可能会导致不同的错误,即线程继续使用资源,相信它拥有锁,而实际上它完全由另一个线程持有。最终,您将尝试计划针对未来编程错误的健壮性,这是一个很好的目标,但有一个限制-互斥只是一个必须小心的东西。
我建议你最好的方法,如果你必须走互斥锁的路线,就是简单地最小化需要互斥锁的代码,并避免阻塞其中的调用。如果您正在实现状态机,请尝试确保互斥锁不必在状态转换之间保持锁定。如果可能,将互斥锁的范围设置为仅在调用链中某个级别的单个函数调用期间保持它们-这使得通过眼睛发现锁定/解锁不匹配变得容易得多。如果您使用的是C++,那么使用RAII可以使您的锁释放更加可靠。
但是再一次,我想你会发现以某种方式序列化你的请求要容易得多,通常是通过声明一个线程作为仲裁器(要么是现有的线程,要么是新的线程)。
发布于 2013-01-18 19:59:39
在共享(和互斥)内存中设置最后一次总线访问的时间戳如何?每一次写入都会如下所示:
<代码>H19解锁互斥锁<代码>H210<代码>G211
发布于 2013-01-18 20:12:29
如果遇到这个问题,我可能会使用另一个“APIwrite”线程来与驱动程序交互。这个线程将循环一个生产者-消费者队列pop和一个休眠(几百毫秒)。任何其他只想写的线程都会在一个*writeBuffer中排队。writeBuffer结构可以包含一个函数(*writeBuffer)指针,APIwrite线程将在写入后调用该指针。此函数由发起线程提供,可以是
向某个事件发出信号,表明原始线程正在等待或可能只是释放*writeBuffer。
省去了显式互斥锁、定时器等的麻烦,并允许同步或异步写入。
https://stackoverflow.com/questions/14398345
复制相似问题