- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified
Queues:
The ready queue is the collection of threads that are waiting for aparticular lock. The Monitor.Wait methods introduce another queue: thewaiting queue. This is required as waiting for a Pulse is distinctfrom waiting to acquire a lock. Like the ready queue, the waitingqueue is FIFO.
Recommended pattern:
These queues can lead to unexpected behaviour. When a Pulse occurs,the head of the waiting queue is released and is added to the readyqueue. However, if there are other threads in the ready queue, theywill acquire the lock before the thread that was released. This is aproblem, because the thread that acquires the lock can alter the statethat the pulsed thread relies on. The solution is to use a whilecondition inside the lock statement
*Q = 队列。
据我所知,当我调用 Pulse
时,它会在结束前做两件事。首先,它从等待 Q 中移除一个线程到就绪 Q。其次,它让就绪 Q 中的一个线程(不知道那个线程是谁)获得锁;它不关心谁获得了锁(来自等待 Q 的线程或出于某种原因处于就绪 Q 中的线程)。
如果我是对的,那么 为什么 在 Monitor.Wait
之前放置一个 while
有助于解决问题(问题 -即使来自等待 Q 的线程未获得锁,脉冲也会结束)?
一个。 请告诉我关于 Monitor.Pulse
的用途是否正确。
B。 为什么我需要在 Monitor.Wait
之前放置一个 while
答案的完整代码如下:
class Program
{
static Queue<int> queue = new Queue<int>();
static object someMonitor = new object();
static void Main(string[] args)
{
Thread Thread1 = new Thread(WorkAlltheTime);
Thread1.Name = "Thread1";
Thread Thread2 = new Thread(WorkAlltheTime);
Thread2.Name = "Thread2";
Thread Thread3 = new Thread(WorkOnce);
Thread3.Name = "Thread3";
Thread1.Start();
Thread2.Start();
Thread.Sleep(1000);
Thread3.Start();
Console.ReadLine();
}
static void WorkAlltheTime()
{
Console.WriteLine("Came in to Ready Q: " + Thread.CurrentThread.Name);
lock (someMonitor)
{
Console.WriteLine("Came out from Ready Q: " + Thread.CurrentThread.Name);
// Broken!
while (queue.Count == 0)
{
Console.WriteLine("Came in to Waiting Q: " + Thread.CurrentThread.Name);
Monitor.Wait(someMonitor);
Console.WriteLine("Came out from Waiting Q: " + Thread.CurrentThread.Name);
}
queue.Dequeue();
Console.WriteLine("Thread: "+Thread.CurrentThread.Name+" Pulled Out");
}
}
static void WorkOnce()
{
lock (someMonitor)
{
queue.Enqueue(1);
Monitor.Pulse(someMonitor);
}
}
}
最佳答案
想象一下,您正在尝试编写一个生产者/消费者队列 - 您每次生产一个项目时都Pulse
,而消费者需要等待直到有一个项目要消费。你会这样写代码:
Foo item;
lock(someMonitor)
{
while (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
假设您没有 while 循环,而是写:
Foo item;
lock(someMonitor)
{
// Broken!
if (queue.Count == 0)
{
Monitor.Wait(someMonitor);
}
item = queue.Dequeue();
}
// Use the item
现在假设您有一个线程已经在等待,然后另一个线程就在锁定语句之前......然后生产者向监视器发出脉冲(当然,并将一个项目添加到队列中)。
到那时,还没有获得锁的线程将第一个获得锁是完全可行的......此时“等待”线程获得锁时,队列将再次为空。只有一个 if
语句,没有循环,当队列为空时,您最终会出列,这将失败。
使用 while 循环,您将再次等待,直到生成下一个项目,这才是您真正想要的。
关于c# - Monitor.Pulse & Wait - 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12121151/
我是 iOS 开发新手。我正在解决的是如何在 iPhone 中运行我的应用程序时获取有关该应用程序的信息。 例如:当我在 Android 中开发时,我连接手机(使用净化模式)并打开 Android M
我仍然不确定这两个调用之间的区别。来自 MSDN, Monitor.Enter(Object) 获取指定对象的独占锁。 Monitor.Wait(Object) 释放对象上的锁并阻塞当前线程,直到它重
我是 GCP 的新手并且来自 Azure 背景。在 GCP 端是否有等效的“Azure Application Insights”用于监控应用程序? 让我用一个例子更清楚地解释我的用例:如果我有一个基
这是说明问题的最小代码: StringBuilder input = new StringBuilder(); void ToUpper() { lock (input) {
我在 ASP.NET 中有一个生产者-消费者场景。我设计了一个Producer 类,一个Consumer 类和一个用于保存共享对象并负责Producer 和Consumer 之间通信的类,我们称它为M
是否可以检测是否是同一个线程试图释放锁?我们在代码中有很多地方看起来像: try { try { if(!Monitor.TryEnter(obj, 2000))
我对并发编程有点陌生,正在尝试了解使用 Monitor.Pulse 和 Monitor.Wait 的好处。 MSDN 的例子如下: class MonitorSample { const in
如果您想在退出和清理对象时阻止执行某些代码块,是否可以使用锁来阻止执行? Monitor.TryEnter(cleanupLock, ref acquiredLock); TryEnter 可用于确保
Monitor.Enter 和 Monitor.Exit 设计为从同一线程调用。但是,如果我需要在与获得的线程不同的线程中释放锁怎么办? 例如:有共享资源和使用该资源的异步操作。该操作以 BeginO
Monitor.PulseAll 通知队列中的所有等待线程。 Monitor.Pulse 通知等待队列中的一个线程。 (下一个等待线程) 只有下一个线程(一个线程)才能获取锁。那有什么区别呢? 什么时
我正在尝试在我的 terraform 代码库中集成对 sshd 进程的 Datadog 监视器检查,但我收到 datadog_monitor.host_is_up2: error updating m
这里的问题是:如果获取对象独占锁的线程(例如通过使用 Monitor.Enter)终止,是否会神奇地释放该对象的独占锁?如果那是真的,那么假设我们从另一个线程调用 Monitor.Exit - 因为我
我正在研究 .NET 中的 Monitor 类,所以我找到了一段似乎可以正常工作的代码,但是当我将它循环一段时间时,它会抛出 OutOfMemoryException。 我在具有 8 GB RAM 的
ECMA-335 规范规定如下: *获取锁(System.Threading.Monitor.Enter 或进入同步方法)应隐式执行 volatile 读取操作,并释放锁(System.Threadi
我在 dll 中使用 OmniThreadLibrary 2.09,主应用程序和 dll 使用相同的 SimpleShareMem 内存管理器。 我用以下代码创建了自己的监视器: FMonitor
我正在使用 R 包 monitoR并收到一条我无法理解的错误消息。 我正在尝试使用 dbUploadTemplate 命令将关联模板列表(“bithTemps”)上传到 MySQL 数据库(“noh”
我想我遗漏了一些关于 Monitor.Enter 和 Monitor.TryEnter 正确行为的信息。这是我编写的一段代码,用于将问题与其余代码分开: object lockObj = new ob
我正在尝试实现一个多线程库,该库将使用线程池同时运行任务。基本上它会从它收到的收集参数中将任务添加到线程池,然后等待直到正在处理的最后一个任务发送脉冲信号。我在早期的测试中取得了成功,但是当我想测试处
我想用redis lua来实现monitor命令,而不是redis-cli monitor。但我不知道怎么办。 redis.call('monitor') 不起作用。 最佳答案 您不能从 Redis
根据语言规范,lock(obj) statement; 会被编译为: object lockObj = obj; // (the langspec doesn't mention this var,
我是一名优秀的程序员,十分优秀!