基于消息的多线程或线程池来执行简短且不常见的操作?
我目前在 .NET 中使用 Retlang 进行基于消息的多线程处理,这是一个很棒的库。我不再有显式锁,每个线程都在做自己的业务,管理应用程序的其部分并通过消息与其他线程通信。
我现在必须实现应用程序的一项功能,该功能也可以拥有自己的发布者/订阅者线程。唯一的问题是这个线程实际上只做很少的工作。预计每 10 分钟左右就会收到一条来自发布者的消息。当收到消息时,它会做一些工作,但不会超过几百毫秒。
所以我开始想知道让一个线程在 99.9% 的时间内处于睡眠状态是否真的是一个不错的选择。有用于此类操作的线程池,但由于我无法控制将接收我的消息的线程,因此我不得不诉诸丑陋且容易出错的锁。
我的问题是:从资源角度来看,让线程处于空闲状态并等待绝大多数时间真的是一个问题吗?在使用良好的基于消息的架构之后使用共享多线程感觉就像回到过去,而且它将是应用程序中唯一带有锁的部分。但我一直在想“我在这里做错了什么吗?”用这个线程。
编辑:谢谢大家,在阅读了你们的每个答案后,我认为另一个线程并不是什么大问题。我的应用程序将仅与基于消息的多线程保持一致,如果我确实有性能问题(但不应该是这种情况),我将进一步调查。
I'm currently using Retlang for message-based multithreading in .NET, which is a great library. I've got no explicit locks anymore, every thread is doing its own business, managing its part of the application and communicating with other threads via messages.
I now have to implement a feature of my application that could also have its own publisher/subscriber thread. The only problem is that this thread will actually do very few work. It's expected to receive a message from a publisher every 10 minutes or so. When a message is received, it will do some work but nothing that should take more than a few hundreds milliseconds.
So I started wondering if having a thread sleeping 99.9% of the time was actually a good choice. There's the thread pool for this kind of operation but since I have no control over which thread my messages will be received, I have to resort to ugly, error-prone locks.
My question is: is it really a problem, resource-wise, to leave a thread idle, waiting the vast majority of time? Using shared multithreading after using a good message-based architecture feels like going back in time, plus it will be the only part of the application with locks. But I keep wondering "Am I doing something wrong here?" with this thread.
Edit: thank you everyone, after reading every of your answers I decided that another thread wasn't so much a problem. My application will stay coherent with only message-based multithreading and if I really have a performance problem (but that shouldn't be the case) I'll investigate further.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我实际上认为,将 ThreadPool 用于大部分时间处于睡眠状态的线程是一个糟糕的设计选择 -
让单个线程处于睡眠状态(或者更好的是等待事件)在应用程序中的开销非常小。使用专用线程的主要缺点是线程需要分配自己的堆栈,因此与线程池线程相比,您将使用一些额外的内存。
I would actually argue that using the ThreadPool for a thread that's sleeping most of the time is a poor design choice -
Having a single thread sleeping (or, better, waiting on an event) has very little overhead in your application. The main disadvantage of using a dedicated thread is that thread will need to have it's own stack allocated, so you'll use a bit of extra memory vs. a threadpool thread.
这听起来像是使用
Task
的理想场景。他们默认使用底层的线程池,但有一个更加进化的 API。This sounds like an ideal scenario to use a
Task
. They use the thread pool by default underneath, but have a much more evolved API.你不能使用Retlang的
PoolFiber
为此?它不是由 ThreadFiber 等专用线程支持,而是由 .Net 线程池支持。这意味着您可以继续使用在整个应用程序中使用的相同 Retlang 语义,而无需保留空闲线程。Can't you use Retlang's
PoolFiber
for this? It isn't backed by a dedicated thread likeThreadFiber
but instead by the .Net threadpool. Which means you can keep using the same Retlang semantics you are using throughout your application without keeping an idle thread.虽然 PoolFiber 上的每个操作都可以在单独的池线程中执行,但特定 PoolFiber 的操作是按顺序执行的,而不是并行执行的,一次只能执行一个池线程。
PoolFiber 应该可以满足您的需求。
While each Action on the PoolFiber can execute in a separate pool thread, the actions for a particular PoolFiber execute sequentially and not in parallel, only one pool thread at a time.
The PoolFiber should do what you are looking for.
我认为这从根本上来说是一个优化问题。您的应用程序是否存在性能问题(特别是内存问题)?如果没有,那么继续让线程空闲并保持代码整洁。一旦你有真正的理由,就探索其他选择。
I think this is fundamentally a question of optimization. Is your application having a performance problem (specifically a memory problem)? If not, then go ahead and leave the thread idle and keep your code cleaner. Explore other options once you have a real reason.
我想说,有一个专门的线程来接收这些消息就很好了。我什至可以说这将是首选方法。这并不像您只是随意创建线程或类似的事情。我们在这里讨论的是一个额外的线程,它不会消耗大量资源(可能会消耗一点堆栈空间)。在我看来,不必担心共享状态的额外同步(当然除了消息传递)的优点胜过缺点。
I would say that having a dedicated thread for receiving these messages fine. I might even goes as far as saying that it would be the preferred method. It is not like you are just creating threads willy-nilly or anything like that. We are talking about one extra thread here and it will not consume a lot resources (maybe a little stack space). The advantage of not having to worry about the additional synchronization of shared state (aside from the message passing of course) trumps the disadvantages in my opinion.
您应该考虑使用 F#。它对于逻辑单线程代理程序的编程非常有用,而无需消耗线程(例如,代理程序可以在 ThreadPool 中跳跃,但仍然以序列化方式响应消息,并且到达其邮箱的消息会唤醒它们并安排 ThreadPool 工作)。
链接
You should consider using F#. It is great for programming logically-single-threaded-agents without burning threads (e.g. agents can hop about the ThreadPool, but still respond to messages in a serialized fashion, and an arriving message at their mailbox wakes them up and schedules ThreadPool work).
Link