我在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正在重新加载随机数量的列表项时,其他正在循环遍历列表的线程,我认为可能会有问题。谁能解释一下为什么程序运行没有问题?
感谢。
答案 0 :(得分:2)
_list
是一个静态变量,这意味着CacheManager
的每个实例都将共享同一个_list
实例。确实应该锁定对_list
的访问以防止并发问题。正如评论中提到的那样,我应该使用ConcurrentCollection
代替List(of T)
,因为List(of T)
不是线程安全的。