- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现一个多线程库,该库将使用线程池同时运行任务。基本上它会从它收到的收集参数中将任务添加到线程池,然后等待直到正在处理的最后一个任务发送脉冲信号。我在早期的测试中取得了成功,但是当我想测试处理起来非常短的任务时遇到了一个奇怪的问题。不知何故,要么在等待命令在主线程中发生之前发送脉冲信号,要么发生其他事情,无论我为同步所做的努力如何,我都无法简单地看到。
为了解决我的问题,我已经实现了另一个“不太理想”的解决方案,因为我正在权衡潜在的性能优势,目前效果很好,但想知道为什么我的第一种方法在这种情况下不起作用首先是案例,尽管在性能方面两者之间没有太大区别。
为了说明,我在简化以下过程后添加了这两种解决方案。有人可以帮我指出哪里出了问题吗?
提前致谢。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace TestcodeBenchmark
{
class Program
{
static int remainingTasks = 10000000;
static Stopwatch casioF91W = new Stopwatch();
static Random rg = new Random();
static readonly object waitObject = new object();
static void Main(string[] args)
{
TestLoop(30, remainingTasks);
Console.ReadKey();
}
private static void TestLoop(int loopCount, int remainingCountResetNumber)
{
for (int i = 0; i < loopCount; i++)
{
remainingTasks = remainingCountResetNumber;
//When this method is called it eventualy stuck at Monitor.Wait line
TestInterlocked();
remainingTasks = remainingCountResetNumber;
//When this method is called it processes stuff w/o any issues.
TestManualLock();
Console.WriteLine();
}
}
private static void TestInterlocked()
{
casioF91W.Restart();
//for (int i = 0; i < remainingTasks; i++)
//{
// ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); });
//}
int toStart = remainingTasks;
//for (int i = 0; i < remainingTasks; i++)
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}
//lock waitObject to be able to call Monitor.Wait
lock (waitObject)
{
//if waitObject is locked then no worker thread should be able to send a pulse signal
//however, if pulse signal was sent before locking here remainingTasks should be
//zero so don't wait if all tasks are processed already
if (remainingTasks != 0)
{
//release the lock on waitObject and wait pulse signal from the worker thread that
//finishes last task
Monitor.Wait(waitObject);
}
}
casioF91W.Stop();
Console.Write("Interlocked:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestInterlockedDecrement()
{
//process task
//TestWork();
//Once processing finishes decrement 1 from remainingTasks using Interlocked.Decrement
//to make sure it is atomic and therefore thread safe. If resulting value is zero
//send pulse signal to wake main thread.
if (Interlocked.Decrement(ref remainingTasks) == 0)
{
//Acquire a lock on waitObject to be able to send pulse signal to main thread. If main
//thread acquired the lock earlier, this will wait until main thread releases it
lock (waitObject)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestManualLock()
{
casioF91W.Restart();
//Acquire the lock on waitObject and don't release it until all items are added and
//Wait method is called. This will ensure wait method is called in main thread
//before any worker thread can send pulse signal by requiring worker threads to
//lock waitObject to be able to modify remainingTasks
lock (waitObject)
{
for (int i = 0; i < remainingTasks; i++)
{
ThreadPool.QueueUserWorkItem(delegate { TestManualDecrement(); });
}
Monitor.Wait(waitObject);
}
casioF91W.Stop();
Console.Write("ManualLock:{0}ms ", casioF91W.ElapsedMilliseconds);
}
private static void TestManualDecrement()
{
//TestWork();
//try to acquire lock on wait object.
lock (waitObject)
{
//if lock is acquired, decrement remaining tasks by and then check
//whether resulting value is zero.
if (--remainingTasks == 0)
{
//send a pulse signal to main thread to continue
Monitor.PulseAll(waitObject);
}
}
}
private static void TestWork()
{
//Uncomment following to simulate some work.
//int i = rg.Next(100, 110);
//for (int j = 0; j < i; j++)
//{
//}
}
}
}
最佳答案
当您开始您的任务时,您循环开始remainingTasks
任务。然而,当您接近 10000 时,一些任务已经完成并将此数字减少到 10000 以下,因此您没有启动正确数量的任务。如果我修改您的循环以保存应启动的任务数,代码将成功运行。 (请注意,您还应该检查 QueueUserWorkItem
的返回值。)
int toStart = remainingTasks;
for (int i = 0; i < toStart; i++)
{
if (!ThreadPool.QueueUserWorkItem(delegate { TestInterlockedDecrement(); }))
Console.WriteLine("Queue failed");
}
关于c# - 在多线程环境中使用 Interlocked.Decrement 以及 monitor.wait 和 monitor.pulse 时的错误行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14062137/
我正在尝试通过连接到我的 linkedin 应用程序将我的博客集成到 Linkedin Pulse。我发现发布到 API /v1/people/~/shares 会分享我的更新,但我不知道如何在 Pu
我正在尝试在我的 GUI 系统中的两个线程之间进行同步。 系统主要任务是初始化两个同步对象并运行两个线程: private FetcherAPI fetcherAPI { get; set; } pr
我有这个生产者/消费者代码: 主要内容: static void Main() { using(PCQueue q = new PCQueue(2)) { for(in
我有一个类,它应该是线程安全的。我最好想用一个同步对象来管理线程安全,以避免复杂的思维破坏,因为所有方法都会改变对象状态变量。因此,我在该对象上用 lock 语句包装方法体。在某些情况下,需要释放锁一
如何制作一个可滚动的Pulse-like导航栏(区域由矩形标记)?有人可以给我举个例子吗? 谢谢吕赖尼 最佳答案 其实很简单。只是嵌套 ScrollView 。外面的覆盖整个屏幕,只允许垂直滚动。 每
如何使 div/input 闪烁或“脉冲”?例如,假设表单字段输入了无效值? 最佳答案 使用 CSS3 类似 on this page ,您可以将脉冲效果添加到名为 error 的类中: @-webk
我遇到了一个问题,我将其简化为这个最小的测试用例,但我仍然不明白为什么它不能正常工作。这里的代码很简单:父线程获取一个锁,然后启动一个子线程,接下来通过启动 await 来释放锁。然后被锁定在同一个锁
我只是想确保我了解这里的内容。如果我使用 Monitor.Enter 或 lock 获得锁定,我是否需要在释放锁定之前调用 Pulse? Monitor.Enter Monitor.Pulse //
他们似乎都实现了相同的目的。我什么时候可以选择一个? 最佳答案 当您的线程正在等待多个事件之一或全部在做某事时,请使用事件。 如果要通过限制可以访问多少线程来限制对数据结构的访问,请使用监视器。 监视
我下载了Sound.Pulse.Simple并复制并粘贴示例程序: main=do s Fractional (GHC.Real.Ratio a) -- Defined in `GHC.R
我想重现active noise-control的效果使用普通耳机和 Linux 计算机的耳机,以便实时静音任何环境噪音(不仅仅是从背景噪音中清除声音输入)。 计划是通过 Alsa/Pulseaudi
我对网络开发知之甚少。 我正在尝试将代码添加到 linkedin 帖子,我尝试了 github Gist 但它不起作用。 有办法还是根本不可能? 最佳答案 似乎仍然(截至 2017 年 11 月 27
我创建了一个脉冲动画,它在 map 上占据一个位置,并持续发出一个脉冲(圆圈)。这按预期工作。但是,我希望脉冲淡出,离点越远。关于如何实现最佳效果有什么想法吗? 动画如下: mCircle =
我想知道如何像应用程序Pulse一样通过表格显示图像。在 iPhone 上。我使用了 UIScrollView 但它并没有太大帮助。它仅以类似数组的方式显示图像,但您无法产生事件或单击图像。 生成 P
我正在尝试优化与 Monitor.Wait 和 Monitor.Pulse 方法类似(基本功能)的异步版本。我们的想法是通过异步方法使用它。 要求:1) 我有一个任务正在运行,它负责等待有人给我的显示
http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified Queues:
根据 MSDN , Monitor.Wait(): Releases the lock on an object and blocks the current thread until it reac
我正在尝试编写一个基本的卷应用程序。由于我是用 Ruby 编写的,因此我不想扩展 C 库或使用 ffi ,而是尝试使用 ruby-dbus 编写它,我使用 Address 获得了 /org/pulse
有没有人在基于 Ubuntu 的 Linux 发行版上成功使用 Juniper Junos 脉冲客户端。 我想知道是否有任何可靠的基于浏览器的 VPN 客户端可以用作替代方案 谢谢 最佳答案 Alex
Delphi Docwiki 解释说 Pulse通知等待队列中的下一个线程,一旦调用线程释放该对象,它将能够锁定指定的对象。 PulseAll向等待队列中的所有线程发出信号。 我found这段代码在线
我是一名优秀的程序员,十分优秀!