【问题标题】:Multi-Thread Member Variable vs Static Variable, How do they work differently in multi-thread?多线程成员变量与静态变量,它们在多线程中的工作方式有何不同?
【发布时间】:2018-03-05 02:44:41
【问题描述】:

我对成员变量和静态变量进行了快速测试,我发现了一个有趣的结果,如果一个变量是静态对象的成员变量,即使在线程竞赛上下文中也总是正确计算,但如果是变量静态变量,它会遇到问题。

例如:

class Program
{

    static void Main(string[] args)
    {
        var locker = new object();
        ThreadPool.SetMaxThreads(64, 64);
        var numOfThreads = 64;


        WaitHandle[] waitHandles = new WaitHandle[numOfThreads];

        var sw = new Stopwatch();
        sw.Start();
        for (long i = 0; i < numOfThreads; i++)
        {
            var handle = new EventWaitHandle(false, EventResetMode.ManualReset);
            waitHandles[i] = handle;
            ThreadPool.QueueUserWorkItem((state) =>
            {

                obj.run();
                ((EventWaitHandle)handle).Set();
            }, handle);
            //obj.run();
        }
        WaitHandle.WaitAll(waitHandles);
        sw.Stop();


        Console.WriteLine($"Exit Performance test {sw.ElapsedMilliseconds} output: {obj.x}");
        Console.ReadKey();
    }
    static MyClass obj = new MyClass();
}

class MyClass
{
    private object locker = new object();
    //public static int x = 0;
    public int x = 0;
    public void run() {
        //lock (locker)
        {
            for (int j = 0; j < 10000000; j++)
            {
                x = x + 1;
            }

            Console.WriteLine($"id: {Thread.CurrentThread.ManagedThreadId}, count of loop: {x}");
        }
        var f = 0;
        Console.WriteLine($"id: {Thread.CurrentThread.ManagedThreadId}, $$start: {f}");
        for (int j = 0; j < 10000000; j++)
        {
            f = f + 1;
        }
        Console.WriteLine($"id: {Thread.CurrentThread.ManagedThreadId}, $$end: {f}");

    }
}

据我了解,静态对象及其成员字段在多线程共享的内存中具有 1 个实例副本,因此它应该与使用静态变量相同,但不知何故它的行为有所不同。

问题: 1. 多线程中的静态字段和成员字段有什么区别? 2.这是否意味着静态字段比成员字段运行得更快?

谢谢!

【问题讨论】:

  • 在这种情况下,您可以使用 Interlocked.Increment。对于更复杂的类型,使用锁或其他一些线程同步方式来避免多个线程并行处理共享资源。
  • 请不要发布代码截图 - 发布代码本身。
  • @Evk 我一定会做到的
  • 我尝试运行您的代码,无论x 是否为静态,我都有相同的行为。您确定在使用静态成员进行测试时没有取消注释 lock (locker) 语句吗?

标签: c# multithreading


【解决方案1】:
  1. 多线程中的静态字段和成员字段有什么区别? 我发现对于 small loops member field 几乎不会遇到多线程竞速问题,但是对于 10000000 的大循环,它们都遇到了竞速问题,因此它们都需要 locker。

  2. 这是否意味着静态字段比成员字段运行得更快? 我发现使用 locker 比没有 locker 写入共享资源要快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2011-06-03
    • 2012-01-14
    • 2012-01-15
    • 1970-01-01
    相关资源
    最近更新 更多