gpt4 book ai didi

c# - 计算多个线程中的东西

转载 作者:太空宇宙 更新时间:2023-11-03 13:07:20 24 4
gpt4 key购买 nike

在我的 .NET 程序中,我想计算一段代码被命中的次数。为了让它更具挑战性,我的代码通常在多个线程中执行,我无法控制线程的创建/销毁(并且不知道它们何时创建)......它们甚至可以被合并。说:

class Program
{
static int counter = 0;

static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();

Parallel.For(0, 100000000, (a) =>
{
Interlocked.Increment(ref counter);
});

Console.WriteLine(sw.Elapsed.ToString());
}
}

由于性能计数器和方法被命中了很多次,我想使用“普通”变量而不是原子/互锁整数。因此,我的第二次尝试是结合使用线程本地存储和 IDisposable 来加快速度。因为我无法控制创建/销毁,所以我必须跟踪存储变量:

class Program
{
static int counter = 0;

// I don't know when threads are created / joined, which is why I need this:
static List<WeakReference<ThreadLocalValue>> allStorage =
new List<WeakReference<ThreadLocalValue>>();

// The performance counter
[ThreadStatic]
static ThreadLocalValue local;

class ThreadLocalValue : IDisposable
{
public ThreadLocalValue()
{
lock (allStorage)
{
allStorage.Add(new WeakReference<ThreadLocalValue>(this));
}
}

public int ctr = 0;

public void Dispose()
{
// Atomic add and exchange
int tmp = Interlocked.Exchange(ref ctr, 0); // atomic set to 0-with-read
Interlocked.Add(ref Program.counter, tmp); // atomic add
}

~ThreadLocalValue()
{
// Make sure it's merged.
Dispose();
}
}

// Create-or-increment
static void LocalInc()
{
if (local == null) { local = new ThreadLocalValue(); }
++local.ctr;
}

static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();

Parallel.For(0, 100000000, (a) =>
{
LocalInc();
});

lock (allStorage)
{
foreach (var item in allStorage)
{
ThreadLocalValue target;
if (item.TryGetTarget(out target))
{
target.Dispose();
}
}
}

Console.WriteLine(sw.Elapsed.ToString());

Console.WriteLine(counter);
Console.ReadLine();
}
}

我的问题是:我们可以做得更快和/或更漂亮吗?

最佳答案

您需要的是一个线程安全的、非阻塞的、volatile , static变量来为您执行计数。


谢天谢地,.NET 框架提供了托管方式来执行您想要的操作。

对于初学者,您需要一个可变的静态变量用作计数器。像这样声明它(所有线程都可以访问它):

public static volatile int volatileCounter; 

static 表示这是一个类而不是实例成员,而 volatile 可防止发生缓存错误。

接下来,您将需要一个以线程安全和非阻塞方式递增它的代码。如果您不希望您的计数器超过 int 变量的限制(这很有可能),您可以使用 Interlocked class对于这样的:

Interlocked.Increment(ref yourInstance.volatileCounter);

interlocked class将保证您的增量操作将是原子的,因此竞争条件不会导致错误的结果,并且它在重量级 sync objects 的方式上也是非阻塞的这里涉及到线程阻塞。

关于c# - 计算多个线程中的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30319656/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com