首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这个算法线程安全吗?

这个算法线程安全吗?
EN

Stack Overflow用户
提问于 2011-07-21 03:02:30
回答 10查看 374关注 0票数 3

我想知道下面的类是否是线程安全的,并在多线程上下文中完美地工作?

代码语言:javascript
复制
public class ThreadSafeClass
{
    private List<int> commandList = new List<int>();
    public void AddCommand(int newCommand)
    {
        lock(syncObj) {
          commandList.Add(newCommand);
        }
    }
    public List<int> Split()
    {
        List<int> oldList = commandList;
        commandList = new List<int>();
        return oldList;
    }
}

ThreadA周期性地调用split方法,许多线程调用AddCommand,split方法中的commandList指向内存中的某个列表,当新列表被赋值时,它的所有内容都在oldList中

split的目的是希望获得所有排队的命令,并在下一次调用中返回其余的命令,...同时让应用程序向commandList添加新项。

因为我专注于split方法,我忘记为add操作添加锁,因为它不是线程安全的,这要归功于:(can poyrazoğlu)但是Split的问题仍然存在。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2011-07-21 13:27:26

这里的问题归结为您对行为的期望。例如,以您的split方法为例:

代码语言:javascript
复制
public List<int> Split()
{
    List<int> oldList = commandList;
    commandList = new List<int>();
    return oldList;
}

在分配oldList和重新分配commandList之间有一段时间,AddCommand方法可以向commandList添加值,这些值将出现在oldList

代码语言:javascript
复制
public List<int> Split()
{
    // Say commandList contains 1 and 2

    List<int> oldList = commandList;

    // Now, on another thread, this happens:
    //
    // AddCommand 3
    // AddCommand 4
    // AddCommand 5
    //
    // The list hasn't been reassigned yet, so at this point oldList and
    // commandList both have 1, 2, 3, 4, and 5.

    commandList = new List<int>();

    // Now, commandList is empty, and oldList contains 1, 2, 3, 4, and 5,
    // even though it only contained 1 and 2 when you first assigned it.

    return oldList;
}

这个序列证明了这样一个事实:oldList不是只包含赋值时的值的快照,而是在赋值到重新赋值commandList之间实际上可以修改的快照。

这段代码中有一件事是正确的,即您添加的每个命令在oldListcommandList中只出现一次。不管有多少线程在调用AddCommand,你都不会遇到任何重复。这听起来像是您要实现的目标,所以我认为您的代码是正确的。

这是因为.NET reference assignment is atomic。在分配commandList期间,对AddCommand的调用不会导致值被添加到多个列表中或根本不被添加。

如果我误解了你的问题,请告诉我。

票数 2
EN

Stack Overflow用户

发布于 2011-07-21 03:06:18

该代码不是线程安全的,因为List.Add不能保证是安全的。(只是第一件事--还有其他问题)。

您也没有锁定共享数据(对commandList的任何访问权限)。

票数 4
EN

Stack Overflow用户

发布于 2011-07-21 03:07:00

拥有线程安全类并不意味着你的程序就是线程安全的。线程安全类只是意味着你可以从多个线程使用它,而且它仍然是好的。线程安全基本上意味着“在多线程环境中保持一致”。

List类不是线程安全的,所以你的代码绝对不是线程安全的。但是这个想法是,即使你使用线程安全的集合,也不意味着你的代码是线程安全的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6767092

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档