ConcurrentDictionary和Dictionary

http://stackoverflow.com/questions/6739193/is-the-concurrentdictionary-thread-safe-to-the-point-that-i-can-use-it-for-a-sta

问题:

Basically, if I want to do the following:

public class SomeClass { private static ConcurrentDictionary<..., ...> Cache { get; set; } }

Does this let me avoid using locks all over the place?

 

解答:

Yes, it is thread safe and yes it avoids you using locks all over the place (whatever that means). Of course that will only provide you a thread safe access to the data stored in this dictionary, but if the data itself is not thread safe then you need to synchronize access to it of course. Imagine for example that you have stored in this cache a List<T>. Now thread1 fetches this list (in a thread safe manner as the concurrent dictionary guarantees you this) and then starts enumerating over this list. At exactly the same time thread2 fetches this very same list from the cache (in a thread safe manner as the concurrent dictionary guarantees you this) and writes to the list (for example it adds a value). Conclusion: if you haven't synchronized thread1 it will get into trouble.

As far as using it as a cache is concerned, well, that's probably not a good idea. For caching I would recommend you what is already built into the framework. Classes such as MemoryCache for example. The reason for this is that what is built into the System.Runtime.Caching assembly is, well, explicitly built for caching => it handles things like automatic expiration of data if you start running low on memory, callbacks for cache expiration items, and you would even be able to distribute your cache over multiple servers using things like memcached, AppFabric, ..., all things that you would can't dream of with a concurrent dictionary.

 

Is the MemoryCache class thread-safe like the ConcurrentDictionary is though? – michael

@michael, yes it is thread safe but absolutely the same remark stands true about synchronizing access to non thread-safe objects that you might be storing into this cache. – Darin Dimitrov

Oh, I understand that part. But, just so that other readers can understand I'm going to reiterate it. You're saying that both the ConcurrentDictionary and MemoryCache class are thread-safe, but the contents within are not guaranteed to be thread-safe. :) – michael 

@michael, exactly, nicely put. My English is so poor that I can't express myself. – Darin Dimitrov 

 

 

ConcurrentDictionary

 internal class Program
    {
        private static void Main()
        {
            try
            {
                var dictionary = new ConcurrentDictionary<string, int>();
                for (char c = 'A'; c <= 'F'; c++)
                {
                    dictionary.TryAdd(c.ToString(), c - 'A' + 1);
                }

                var iterationTask = new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        Console.WriteLine(pair.Key + ":" + pair.Value);
                    }
                });

                var updateTask = new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        dictionary[pair.Key] = pair.Value + 1;
                    }
                });

                var addTask = new Task(() =>
                {
                    for (char c = 'G'; c <= 'K'; c++)
                    {
                        //dictionary[c.ToString()] = c - 'A' + 1;
                        bool flag = dictionary.TryAdd(c.ToString(), c - 'A' + 1);
                        if (!flag)
                        {
                            Console.WriteLine("添加{0}失败", c);
                        }
                        else
                        {
                            Console.WriteLine("添加{0}成功", c);
                        }
                    }
                });

                var deleteTask=new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        if (Convert.ToChar(pair.Key) <= 'F')
                        {
                            int number;
                            bool flag = dictionary.TryRemove(pair.Key, out number);
                            if (!flag)
                            {
                                Console.WriteLine("移除{0}失败", pair.Key);
                            } 
                            else
                            {
                                Console.WriteLine("移除{0}成功", pair.Key);
                            }
                        }
                    }
                });

                updateTask.Start();
                iterationTask.Start();
                addTask.Start();
                deleteTask.Start();
                Task.WaitAll(updateTask, iterationTask,addTask,deleteTask);

            }
            catch (Exception ex)
            {
                while (ex != null)
                {
                    Console.WriteLine(ex.Message);
                    ex = ex.InnerException;
                }
            }
            Console.ReadLine();
        }
    }

执行结果几乎每次都不相同,但是总能成功执行。

 

 

Dictionary

非线程安全的,代码执行的时候,会提示,集合已修改

internal class Program
    {
        private static void Main()
        {
            try
            {
                var dictionary = new Dictionary<string, int>();
                for (char c = 'A'; c <= 'F'; c++)
                {
                    dictionary.Add(c.ToString(), c - 'A' + 1);
                }

                var iterationTask = new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        Console.WriteLine(pair.Key + ":" + pair.Value);
                    }
                });

                var updateTask = new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        dictionary[pair.Key] = pair.Value + 1;
                    }
                });

                var addTask = new Task(() =>
                {
                    for (char c = 'G'; c <= 'K'; c++)
                    {
                        dictionary.Add(c.ToString(), c - 'A' + 1);
                    }
                });

                var deleteTask = new Task(() =>
                {
                    foreach (var pair in dictionary)
                    {
                        if (Convert.ToChar(pair.Key) <= 'F')
                        {
                            bool flag = dictionary.Remove(pair.Key);
                            if (!flag)
                            {
                                Console.WriteLine("移除{0}失败", pair.Key);
                            }
                            else
                            {
                                Console.WriteLine("移除{0}成功", pair.Key);
                            }
                        }
                    }
                });

                updateTask.Start();
                iterationTask.Start();
                addTask.Start();
                deleteTask.Start();
                Task.WaitAll(updateTask, iterationTask, addTask, deleteTask);

            }
            catch (Exception ex)
            {
                while (ex != null)
                {
                    Console.WriteLine(ex.Message);
                    ex = ex.InnerException;
                }
            }
            Console.ReadLine();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值