线程安全的内部线程工作者
我想知道如何在执行线程内部做到线程安全,让我通过示例解释一下:
假设我想要一个命令管道,这些命令应该一个接一个地连续执行,但在我的线程中我等不及了他们。线程通常处于睡眠状态,如果某个命令入队,则线程被唤醒,然后执行队列中的所有命令,并再次进入睡眠模式,直到新命令入队。比如:
public void Enqueue(ICommand command)
{
this.queue.Enqueue(command);
this.synchroHandler.Set();
}
private void Pipeline()
{
while (true)
{
this.synchroHandler.WaitOne();
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
// what if command will be enqueued between previous command - HERE
// ... and this command HERE
this.synchroHandler.Reset();
}
}
public void Main()
{
this.queue = new ThreadSafeQueue<ICommand>();
this.computionHandler = new ManualResetEvent(false);
Thread thread = new Thread(new ThreadStart(this.Pipeline));
thread.Start();
// start adding commands to pipeline
this.Enqueue(command1);
this.Enqueue(command2);
...
}
假设我的队列实现是线程安全的,所以 this.queue.Count、this.queue.Enqueue 和 this.queue.Dequeue 使用相同的锁。示例中显示的 Ss 是否将在“}”和 this.synchroHandler.Reset() 之间调用 public Enqueue();即使队列中有一项,线程也会最终休眠(this.synchroHandler.Set() 将在 this.synchroHandler.Reset() 之前调用)。知道如何使这个模式线程安全吗?
I am wondering how to do inside executional thread to be thread safe, let me explain it by example:
lets say that I want to have pipeline of commands which should be executed continuously one by one, but in my thread I can't wait for them. Thread is normally slept, is awaeken if some command is enqueued, then it executes all commands in the queue and again goes to sleeping mode until new command is being enqueued. something like:
public void Enqueue(ICommand command)
{
this.queue.Enqueue(command);
this.synchroHandler.Set();
}
private void Pipeline()
{
while (true)
{
this.synchroHandler.WaitOne();
while (this.queue.Count > 0)
{
ICommand command = this.queue.Dequeue();
command.Execute();
}
// what if command will be enqueued between previous command - HERE
// ... and this command HERE
this.synchroHandler.Reset();
}
}
public void Main()
{
this.queue = new ThreadSafeQueue<ICommand>();
this.computionHandler = new ManualResetEvent(false);
Thread thread = new Thread(new ThreadStart(this.Pipeline));
thread.Start();
// start adding commands to pipeline
this.Enqueue(command1);
this.Enqueue(command2);
...
}
lets say my implementation of queue is thread-safe so this.queue.Count, this.queue.Enqueue and this.queue.Dequeue use same lock. Ss shown in the example if public Enqueue() will be invoked between the "}" and this.synchroHandler.Reset(); thread will ends up slept even if it has one item in the queue (this.synchroHandler.Set() will be invoked right before this.synchroHandler.Reset()). Any idea how to make this schema thread-safe?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
查看 BlockingCollection
, System.Collections.Concurrent 中的线程安全生产者-消费者命名空间。Check out BlockingCollection
<T>
, thread safe producer-consumer in System.Collections.Concurrent namespace.您应该在 WaitOne() 之后立即调用 this.synchroHandler.Reset()。
因此,如果在Reset之前调用Queue,您将进入while循环,如果在检查queue.Count之后调用Queue,则下次调用WaitOne()时,它将立即返回并进入while循环。
You should call this.synchroHandler.Reset() right after WaitOne().
Therefore if Queue is called before the Reset, you will enter the while loop and if its called after you checked the queue.Count, the next time you call WaitOne(), it will return immediately and go into the while loop.
你能把它改成旋转吗?因此,每隔 10 毫秒,线程就会醒来并检查队列是否有项目,否则会再次进入睡眠状态。
Can you change it to spin? So, every 10ms, the thread wakes up and checks to see if the Queue has an item, otherwise is goes to sleep again.