当每个线程访问静态共享列表中的唯一元素/ ID时,是否需要锁定?

时间:2017-08-24 21:19:18

标签: c# multithreading locking

我有一个在多线程应用程序中使用的共享C#public static List<long>

登录后,检查用户的“ID”(这是一个独特的'长'  执行以确定它是否包含在此共享列表中,如果没有,则用户的ID将添加到此共享列表。

注销后,此用户的ID将从共享列表中删除(假设在删除之前检查用户的ID是否在列表中)。用户无权访问其ID。

问题:是否有锁访问上述场景中所需的共享列表对象?如果是这样,执行的哪个序列将导致意外数据?

Byrd要求代码。以下是一些反映上述问题/场景的通用代码:

public class MyApp
{
    public static readonly object _userIDs = new object();
}

void Login(long uniqueUserID)
{
    if (_userIDs.Contains(uniqueUserID) == false)
    {
        _userIDs.Add(uniqueUserID);
    }
}

void LogOut(long uniqueUserID)
{
    if (_userIDs.Contains(uniqueUserID) == true)
    {
        _userIDs.Remove(uniqueUserID);
    }
}

1 个答案:

答案 0 :(得分:0)

在访问同一列表的多线程应用程序中,除非先将其锁定,否则这可能是灾难性的。

当你在没有线程的情况下迭代列表时,你不能这样做。

List<object> dataList = new List<object>(){"foo","bar","my","list"}
foreach(object o in dataList){
     dataList.Remove(o);
}

不确定确切的错误是什么,但是,当您迭代它时,您正在更改正在迭代的对象的值。它会崩溃。

如果您将其添加到“以后删除”列表中,那么让线程删除之后应该没问题的数据。像这样......

List<object> dataList = new List<object>(){"foo","bar","my","list"};
List<object> toRemoveLater = new List<object>();
foreach(object o in dataList){
     toRemoveLater.Add(o);
}
foreach(object o in toRemoveLater ){
     dataList.Remove(o);
}

在多线程应用程序中,虽然您很可能会遇到并发修改错误,因为您正在更改内存中的值而另一个线程正在迭代它。

但是,有一些线程安全列表会强制其他线程轮流等待内存。这取决于你正在做什么,看到你的代码可能会有所帮助。