我应该在多线程中锁定局部变量吗?

时间:2016-05-04 18:20:01

标签: c# multithreading local-variables

我在c#中测试简单的缓存逻辑。这是我的CacheManager类:

public class CacheManager
{
    static List<string> _list = new List<string>();
    static readonly object _syncobject = new object();

    public static void ReloadList()
    {
        List<string> list = new List<string>();

        Random r = new Random();
        var count = r.Next(10);

        for (int i = 0; i < count; i++)
        {
            list.Add("list" + i);
        }

        //lock (_syncobject)
        {
            _list = list;
        }

    }


    public static IEnumerable<string> GetList()
    {
        //lock (_syncobject)
        {
            return _list;
        }
    }

}

下面是生成许多使用CacheManager的线程的类:

class Program
{
    static void Main(string[] args)
    {

        //threads for re-loading the list
        for (int i = 0; i < 3; i++)
        {
            Thread reloadThread = new Thread(ReloadList);
            reloadThread.Start();
        }

        //threads for getting the list
        for (int i = 0; i < 10; i++)
        {
            Thread tget = new Thread(PrintList);
            tget.Start();
        }

        //threads for getting the list and storing in local variable then use it
        for (int i = 0; i < 10; i++)
        {
            Thread tget = new Thread(PrintListWithLocalVariable);
            tget.Start();
        }

        Console.ReadKey();

    }

    private static void ReloadList()
    {
        do
        {
            Console.WriteLine("Reloading **********");
            CacheManager.ReloadList();

        } while (true);
    }

    private static void PrintList()
    {
        do
        {
            foreach (var item in CacheManager.GetList())
            {
                if (item == null)
                    throw new Exception("i == null");

                Console.WriteLine(item);
            }

        } while (true);
    }

    private static void PrintListWithLocalVariable()
    {
        do
        {
            var list = CacheManager.GetList();
            foreach (var listitem in list)
            {
                var i = list.FirstOrDefault(x => x.Equals(listitem));
                if (i == null)
                    throw new Exception("i == null");
                Console.WriteLine("Printing with Local variable:" + listitem);
            }

        } while (true);
    }


}

我的理解是我们应该在CacheManager中锁定_list变量,但看起来并不像我们需要的那样。我跑了上面的测试一个小时左右,但没有得到任何错误。当ReloadThread正在重新加载随机数量的列表项时,其他正在循环遍历列表的线程,我认为可能会有问题。谁能解释一下为什么程序运行没有问题?

感谢。

1 个答案:

答案 0 :(得分:2)

_list是一个静态变量,这意味着CacheManager的每个实例都将共享同一个_list实例。确实应该锁定对_list的访问以防止并发问题。正如评论中提到的那样,我应该使用ConcurrentCollection代替List(of T),因为List(of T)不是线程安全的。