VJA*_*JAI 5 .net c# concurrency multithreading locking
我有一个包含静态集合的类,用于将登录用户存储在ASP.NET MVC应用程序中.我只是想知道下面的代码是否是线程安全的.每当我向onlineUsers集合添加或删除项目时,是否需要锁定代码.
public class OnlineUsers
{
private static List<string> onlineUsers = new List<string>();
public static EventHandler<string> OnUserAdded;
public static EventHandler<string> OnUserRemoved;
private OnlineUsers()
{
}
static OnlineUsers()
{
}
public static int NoOfOnlineUsers
{
get
{
return onlineUsers.Count;
}
}
public static List<string> GetUsers()
{
return onlineUsers;
}
public static void AddUser(string userName)
{
if (!onlineUsers.Contains(userName))
{
onlineUsers.Add(userName);
if (OnUserAdded != null)
OnUserAdded(null, userName);
}
}
public static void RemoveUser(string userName)
{
if (onlineUsers.Contains(userName))
{
onlineUsers.Remove(userName);
if (OnUserRemoved != null)
OnUserRemoved(null, userName);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 13
这绝对不是线程安全的.任何时候2个线程正在做某事(在Web应用程序中很常见),混乱是可能的 - 异常或静默数据丢失.
是的,你需要某种同步,如lock; 和static通常用于数据存储,IMO一个非常糟糕的主意(除非非常小心地处理和有限的物像的配置数据).
此外 - static事件以使对象图意外存活的好方法而臭名昭着.也要谨慎对待; 如果您只订阅一次,很好 - 但不要按订阅订阅等.
此外 - 它不仅仅是锁定操作,因为这一行:
return onlineUsers;
Run Code Online (Sandbox Code Playgroud)
返回您的列表,现在不受保护.必须同步对项目的所有访问权限.就个人而言,我会返回一份副本,即
lock(syncObj) {
return onlineUsers.ToArray();
}
Run Code Online (Sandbox Code Playgroud)
最后,.Count从这样做返回可能会令人困惑 - 因为它不能保证Count在任何时候.它仅在该时间点是信息性的.