【问题标题】:How to output data form a thread to another thread without locking?如何在不锁定的情况下将数据从一个线程输出到另一个线程?
【发布时间】:2010-10-06 11:01:50
【问题描述】:

我正在开发 DirectShow 应用程序。我遇到了一个死锁问题,这个问题似乎是由线程调用的回调函数中的获取锁引起的。这是我在 MSDN 论坛上问的问题:

http://social.msdn.microsoft.com/Forums/en-US/windowsdirectshowdevelopment/thread/f9430f17-6274-45fc-abd1-11ef14ef4c6a

现在我必须避免在该线程中获取锁。但问题是,我必须将音频输出到另一个线程,我怎样才能将数据不加锁地放到另一个线程?

有人告诉我,我可以使用 win32 sdk 的 PostMessage 将数据发布到另一个线程。但是,为了得到消息,我必须运行一个 Windows 程序。我的程序是一个 Python C++ 扩展模块。添加循环来拉取消息可能非常困难。所以我认为另一种在线程之间传递数据而不锁定的方法。 (其实……生产者线程不能被锁定,但是消费者线程可以做到。)

锁还是不锁,这是个问题。

那么问题来了怎么办?

谢谢。

--------编辑-----

我想我知道为什么会出现死锁,那可能不是 DirectShow 的问题。

主线程归Python所有,调用stop,即持有GIL。并在线程返回中停止等待 DirectShow 的回调。但是回调获取 GIL。

看起来像这样

Main(Hold GIL) -> Stop(Wait callback) -> Callback(Wait GIL) -> GIL(Hold by Main thread)

该死的!这就是为什么我不太喜欢多线程的原因。 无论如何,谢谢你的帮助。

【问题讨论】:

  • 您在 Windows 95/98 上工作吗?如果不是,那么你的操作系统是什么?
  • 糟糕,我想我知道它为什么会陷入僵局。主线程拿到GIL,调用stop,stop等待callback,callback等待GIL。

标签: multithreading message-queue deadlock directshow


【解决方案1】:

如果您在纯 Python 中执行此操作,我会使用 Queue 对象;这些缓冲了写入但在读取时阻塞的数据,直到有东西可用,并在后台进行任何必要的锁定。

这是一种极其常见的数据类型,无论您当前使用何种语言或工具链,都应该始终提供一些等效的数据类型;例如,在 C++ 中有一个可用的 STL 队列,但标准没有指定线程安全特性(请参阅您的本地实现文档)。

【讨论】:

  • 是的,我可以使用 STL 队列来放置和拉取数据,但问题是我必须在放置或拉取某些东西之前锁定该队列。我必须避免在生产者线程中获取锁。
  • 仅供参考:调用 PyGILState_Ensure 和 DirectShow 的 contorl->stop() 时会发生死锁。甚至 PyGILState_Ensure 和 seek->Seek(...)。所以我认为在 DirectShow 回调期间我无法获取锁。
【解决方案2】:

好吧,如果您的两个线程都可以处理相同数据的重复副本,理论上可以避免锁定。在 MSDN 论坛中阅读您的问题后...

“所以为了避免死锁,我不应该在抓取回调函数中获取任何锁?如果我想将音频输出到另一个线程怎么办?”

我认为您应该能够将音频数据存放在出列队列(STL 类)中,然后从另一个线程中获取这些数据。然后,这个其他线程可以处理您的音频数据。

我很高兴您的问题已经解决,因为我询问您的操作系统的原因是您提到的文档说您不应该因为 win16Mutexes 的一些问题而等待其他线程。 Windows XP 上没有 win16mutexes(程序在 ntvdm/wow16 上运行时除外),因此您应该能够使用锁来同步这些线程。

【讨论】:

  • 该线程是否可以安全地将数据放入出队并从另一个线程中提取?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2023-02-19
  • 1970-01-01
  • 2015-07-20
  • 2023-03-24
相关资源
最近更新 更多