c# 锁定数组与数组索引

c# lock on Array vs Index of Array

给出下面的代码

var array = new object[10];
for(int x = 0;x<array.Length;x++)
    array[x] = new object();


//Lock on Array
lock(array){
    //Do Stuff
}

//Lock on object of array
lock(array[1]){
    //Do Stuff
}

//lock on another object
var o = array[1];
lock(o){
    //Do Stuff
}

第一个锁定语句将锁定对象 array

但是在第二个锁定语句中,锁定是发生在数组索引 1 处的对象上,还是也发生在对象 array 上?另一种提问方式,第二把锁和第三把锁的行为是否相同?

由于多线程的复杂性,我从来都不喜欢使用 lock。回答我的问题,这里使用下面的代码是结果。

场景 2 和场景 3 是等价的。这些锁语句相互干扰(这是通过查看代码所期望的)。

场景 1 不干扰场景 2 或场景 3。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        public static object o;
        public static object[] array;

        static void Main(string[] args)
        {
            array = new object[10];

            for (int x = 0; x < array.Length; x++)
                array[x] = new object();

            o = array[1];
            var tasks = new Task[100];
            Task t;


            //t = Task.Run(() => lockArray(5000));
            t = Task.Run(() => lockArrayIndex(5000));
            //t = Task.Run(() => lockObject(5000));
            for (int i = 0; i < tasks.Length; i++)
            {
                //tasks[i] = Task.Run(() => lockArray(1000));
                //tasks[i] = Task.Run(() => lockArrayIndex(1000));
                tasks[i] = Task.Run(() => lockObject(1000));
            }



            Task.WaitAll(tasks);

            "done".Dump();
            Console.ReadKey();
        }

        private static void lockArray(int input)
        {
            //Lock on Array
            lock (array)
            {
                System.Threading.Thread.Sleep(input);
                "Array".Dump();
            }
        }

        private static void lockArrayIndex(int input)
        {
            //Lock on object of array
            lock (array[1])
            {
                System.Threading.Thread.Sleep(input);
                "Array[1]".Dump();
            }
        }

        private static void lockObject(int input)
        {
            //lock on another object
            lock (o)
            {
                System.Threading.Thread.Sleep(input);
                "o".Dump();
            }
        }
    }

    public static class extenstions
    {
        public static void Dump(this string input)
        {
            Console.WriteLine(input);
        }
    }
}