在多线程场景中正确锁定 List

2024-06-26

好吧,我只是无法正确理解多线程场景。抱歉再次问类似的问题,我只是在互联网上看到许多不同的“事实”。

public static class MyClass {
    private static List<string> _myList = new List<string>;
    private static bool _record;

    public static void StartRecording()
    {
        _myList.Clear();
        _record = true;
    }

    public static IEnumerable<string> StopRecording()
    {
        _record = false;
        // Return a Read-Only copy of the list data
        var result = new List<string>(_myList).AsReadOnly();
        _myList.Clear();
        return result;
    }

    public static void DoSomething()
    {
        if(_record) _myList.Add("Test");
        // More, but unrelated actions
    }
}

这个想法是,如果激活了 Recording,对 Do Something() 的调用就会记录在内部列表中,并在调用 Stop Recording() 时返回。

我的规格是这样的:

  • StartRecording 不被视为线程安全的。用户应该在没有其他线程调用 DoSomething() 时调用此方法。但如果能以某种方式实现,那就太好了。
  • StopRecording 也不是正式的线程安全的。再说一遍,如果可以的话那就太好了,但这不是必需的。
  • DoSomething 必须是线程安全的

通常的方式似乎是:

    public static void DoSomething()
    {
        object _lock = new object();
        lock(_lock){
            if(_record) _myList.Add("Test");
        }
        // More, but unrelated actions
    }

或者,声明一个静态变量:

    private static object _lock;

    public static void DoSomething()
    {
        lock(_lock){
            if(_record) _myList.Add("Test");
        }
        // More, but unrelated actions
    }

然而,这个答案 https://stackoverflow.com/questions/230716/difference-between-locklocker-and-lockvariablewhichiamusing/230861#230861表示这不会阻止其他代码访问它。

所以我想知道

  • 我如何正确锁定列表?
  • 我应该在函数中创建锁对象还是作为静态类变量创建?
  • 我可以将 Start 和 StopRecording 的功能也包装在锁块中吗?
  • StopRecording() 做了两件事:将布尔变量设置为 false(以防止 DoSomething() 添加更多内容),然后复制列表以将数据的副本返回给调用者)。我假设 _record = false;是原子的并且会立即生效吗?所以通常我根本不必担心这里的多线程,除非其他线程再次调用 StartRecording() ?

归根结底,我正在寻找一种方式来表达“好吧,这个列表现在是我的了,所有其他线程都必须等到我完成它”。


我将在这里锁定 _myList 本身,因为它是私有的,但使用单独的变量更常见。改进几点:

public static class MyClass 
{
    private static List<string> _myList = new List<string>;
    private static bool _record; 

    public static void StartRecording()
    {
        lock(_myList)   // lock on the list
        {
           _myList.Clear();
           _record = true;
        }
    }

    public static IEnumerable<string> StopRecording()
    {
        lock(_myList)
        {
          _record = false;
          // Return a Read-Only copy of the list data
          var result = new List<string>(_myList).AsReadOnly();
          _myList.Clear();
          return result;
        }
    }

    public static void DoSomething()
    {
        lock(_myList)
        {
          if(_record) _myList.Add("Test");
        }
        // More, but unrelated actions
    }
}

请注意,此代码使用lock(_myList)同步访问两个 _myListand_记录。并且您需要同步这两者上的所有操作。

并同意这里的其他答案,lock(_myList)对 _myList 不执行任何操作,它只是使用 _myList 作为令牌(可能作为 HashSet 中的键)。所有方法都必须通过使用相同的令牌请求许可来公平竞争。另一个线程上的方法仍然可以使用 _myList 而无需先锁定,但结果不可预测。

我们可以使用任何令牌,因此我们经常专门创建一个令牌:

private static object _listLock = new object();

然后使用lock(_listLock)代替lock(_myList)到处。

如果 myList 是公开的,则该技术是可取的,并且如果您重新创建 myList 而不是调用 Clear(),则该技术是绝对必要的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在多线程场景中正确锁定 List? 的相关文章

  • 在 SpriteKit 中,touchesBegan 是否与 SKScene 更新方法在同一线程中运行?

    在 Apple 文档中高级场景处理 https developer apple com library ios documentation GraphicsAnimation Conceptual SpriteKit PG Actions
  • 如何将 QSerialPort 模块添加到 CMake 中?

    我想将 QSerialPort 模块添加到 CMake 中 根据我的理解 我需要将QT 串口添加到 pro中 我只想使用 CMake 所以我尝试编译简单的 CMake 文件 但有错误 QtCore 正在工作 qDebug 可以毫无问题地显示
  • ObjectTrackingEnabled 和 linq-to-sql

    I read here http www sidarok com web blog content 2008 05 02 10 tips to improve your linq to sql application performance
  • 命令中带空格的 Windows C 系统调用

    我无法使用名称和参数中的空格进行系统调用 例如 system c program files something example exe c my files example txt 我尝试过各种我知道的方法来逃避 但没有任何效果 我努力了
  • Linux C++ 调试器

    我正在寻找完美的 Linux C 调试器 我不期望成功 但搜索应该提供丰富的信息 我是一个非常有能力的 gdb 用户 但 STL 和 Boost 很容易压垮我的调试技能 并不是说我无法深入了解数据结构的内部结构 而是它需要很长时间 我通常会
  • 持续运行的 C# 代码 - 服务还是单独的线程?

    我有一个 NET 4 Web 应用程序 它有 3 个关联的独立项目 DAL BAL 和 UI 我正在使用实体框架进行数据库交互 我有代码循环遍历一堆数据库数据 根据找到的内容调用方法 然后更新数据库 我希望这段代码一直运行 同时 我希望用户
  • argc 和 argv 在 Windows 中没有用吗?

    在 Linux 中 argc 和 argv 计算终端中的参数 但在 Windows 中 我找不到放置第二个参数的地方 事实上 每次我运行该程序时 它都会创建那个丑陋的黑色窗口 我什至没有机会给出任何争论 那么这两个变量在Windows平台下
  • 如何让 PCRE 与 C++ 一起使用?

    这是一个新手问题 但我希望我能尽可能清楚地表达我的问题 我正在尝试用 C 进行模式匹配 我已经从以下位置下载了 PCRE 的 Win32 版本here http gnuwin32 sourceforge net packages pcre
  • WPF MVVM后台打印数据绑定问题

    我正在使用 wpf mvvm 开发一个销售点应用程序 在交易生命周期的许多阶段 都会在后台打印收据 我已经使用其他示例在后台生成和打印收据 我正在后台打印一个 UserControl 一切看起来都很棒 然后 我为该控件创建了 ViewMod
  • 剥离 OLE 标头信息 (MS Access / SQL Server)

    我有一个 C 应用程序需要支持二进制数据库内容 图像等 当使用 MS Access 或 MS SQL Server 时 此数据被包装在 OLE 对象内 如何去除此 OLE 标头信息 请注意 我不能只查找特定标签的开头 因为内容可以是 png
  • 简单的喷射器将具体类型与生活方式结合起来

    我正在寻找一种可以使用指定的生活方式注册具体类型的方法 基本上如下所示 public void SomeFunction Type concrete Lifestyle lifestyle gt container Register con
  • 链接错误:xxx 已在 *****.LIB 中定义:: 究竟出了什么问题?

    Problem 我正在尝试使用一个名为DCMTK http dicom offis de dcmtk它使用了一些其他外部库 zlib libtiff libpng libxml2 libiconv 我已经从同一网站下载了这些外部库 LIB
  • 防止单个可执行文件的多个进程实例

    我正在使用 NET 和 C 我想阻止同一可执行文件的两个实例同时运行 但我不想阻止从另一个文件夹运行的同一进程 例如 我有一个位于两个不同位置的可执行文件 C MyProject Master Program exe C MyProject
  • 没有类型的 IEnumerable 属性

    我正在尝试创建一个类似于来自 MSDN 的官方 DataGrid ItemsSource 的属性 public IEnumerable ItemsSource get set 这提供了对任何派生类中任何类型的支持 有了这个 我可以设置类似的
  • Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

    我有以下 Subsonic 3 0 查询 其中包含嵌套的 NotIn 查询 public List
  • 合并大文件的最佳方法是什么?

    我必须合并数千个大文件 每个大约 200MB 我想知道合并这些文件的最佳方法是什么 行将有条件地复制到合并文件中 可以使用 File AppendAllLines 或使用 Stream CopyTo 吗 使用 File AppendAllL
  • PC 上 XNA 中的信箱和缩放

    有没有一种方法可以让我基本上以 1080p 或 720p 作为默认分辨率来开发 XNA 游戏 然后根据设置的分辨率将游戏中的所有内容缩放到适当的大小 而不必在每个 Sprite 中设置缩放因子Draw 方法 我的想法是 我可以基于 1080
  • Task.Delay 到底是如何工作的?

    他们说 Task Delay 是一个异步 Thread Sleep 为了测试这一点 我写了下面的代码 我希望立即打印 One 然后 3 秒后将打印结果变量 15 2 秒后 将打印 Two 但似乎并非如此 一 不会立即打印 3 秒后打印 On
  • 64 位随机生成器种子

    我目前正在运行一个具有 8 个以上管道 线程 的多线程模拟应用程序 这些管道运行非常复杂的代码 该代码取决于种子生成的随机序列 然后该序列被归结为单个 0 1 我希望在将种子从主线程传递到处理管道后 这种 随机处理 具有 100 的确定性
  • Java中ThreadFactory的使用

    有人可以简要解释一下如何以及何时使用 ThreadFactory 吗 使用和不使用 ThreadFactory 的示例可能确实有助于理解差异 Thanks 这是一种可能的用法 假设您有一个ExecutorService它执行你的Runnab

随机推荐

  • Keras 多输入 AttributeError:“NoneType”对象没有属性“inbound_nodes”

    我正在尝试构建一个模型 如下图所示 这个想法是采用多个分类特征 one hot 向量 并分别嵌入它们 然后将这些嵌入向量与 LSTM 的 3D 张量组合起来 在以下代码中Keras2 0 2 当创建Model 具有多个输入的对象 它会引发A
  • 使用 Python Unescape _xHHHH_ XML 转义序列

    我正在使用 Python 2 x 不可协商 读取 XML 文档 由其他人创建 这些文档允许许多元素的内容通过使用转义来包含不是有效 XML 字符的字符 xHHHH 公约例如ASCII BEL 又名 U 0007 由 7 个字符序列表示u x
  • 致命错误:找不到“Fabric/Fabric.h”文件

    我正在使用 xcode 6 3 1 OSX 10 10 3 并且我已经在本地系统上成功配置了 crashlytics 它工作正常 并通过 Fabric 应用程序发布构建 但是当我将相同的代码库转移到 teamcity 时 它向我显示以下错误
  • 使用 gstreamer 组合音频和视频流[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用 gstreamer 通过 RTP 流将 mp4 mpeg 4 文件从一台设备流式传输到另一台设备 基本上 我将 mp4 文件拆
  • Eclipse Indigo 中 Maven 的依赖关系层次结构视图

    似乎无法使用最新版本的 eclipse Indigo SR2 获取依赖关系层次结构视图 这post https stackoverflow com questions 6475927 maven pom editor dependency
  • JavaScript 中多个数组的笛卡尔积

    如何在 JavaScript 中实现多个数组的笛卡尔积 举个例子 cartesian 1 2 10 20 100 200 300 应该返回 1 10 100 1 10 200 1 10 300 2 10 100 2 10 200 2020
  • WCF、Rest 和 SOAP 之间是什么关系?

    WCF和REST SOAP是什么关系 WCF 是基于其中一种技术 REST 或 SOAP 还是一种单独的技术 WCF 是一个用于构建分布式系统的消息传递框架 分布式系统是mostly只是网络服务的另一种说法 这意味着您可以用 C 或任何 N
  • Cmake 错误未定义对“pthread_create”的引用

    我对 cmake FindThreads 进行了测试 这是我的源代码test cpp和CMakeLists txt include
  • n 是负数、正数还是零?返回 1、2 或 4

    我正在构建一个 PowerPC 解释器 它运行得很好 在 Power 架构中 条件寄存器 CR0 x86 上的 EFLAGS 几乎在任何指令上都会更新 是这样设置的 如果最后的结果为负 则 CR0 的值为 1 如果最后的结果为正 则 CR0
  • Flutter Firebase Cloud函数无法调用

    当我尝试从 Flutter 调用可调用函数时 在使用 Firebase Cloud Functions 时遇到错误 flutter caught generic exception flutter PlatformException fun
  • 如何在 Angular 中实现像 Windows 中那样的 IP 地址输入框?

    我想实现一个输入框 以便用户可以输入 IP 地址和端口 端口可以是可选的 我想让它像 Windows 中那样有 3 个点 我尝试过使用 GitHub 上的一些掩码组件 但是当我想输入 IP 时 输入框将如下所示 10 1 40 所以我无法提
  • 是否有任何方法可以帮助解决常见的 SQLite 问题?

    通常 相对简单的错误会导致问题 而这些问题往往因对 SQLite 的误解而变得更加复杂 例如 未找到表和列 因为通常认为onCreate的方法DBHelper 的子类SQLiteOpenHelper每次创建 DBHelper 实例或每次运行
  • pySpark 映射多列

    我需要能够使用多列比较两个数据帧 pySpark尝试 get PrimaryLookupAttributeValue values from reference table in a dictionary to compare them t
  • Terraform:错误:Kubernetes 集群无法访问:配置无效

    使用 terraform destroy 删除 kubernetes 集群后 我无法再创建它 terraform apply 返回以下错误消息 错误 Kubernetes 集群无法访问 配置无效 否 已提供配置 尝试设置 KUBERNETE
  • C++向量数组运算符计算成本高?

    我一直都知道 C 的丰富抽象会带来一定的计算开销 但我的印象是 一旦应用了正确的编译器优化 这种开销几乎可以忽略不计 我很好奇这种开销到底有多大 所以我编写了一个简单的测试来确定这一点 该测试是一个模板化函数 它接受一个容器变量 为容器中的
  • 检测 UTF-8 编码文本文件中的损坏字符

    我有一个使用错误的字符编码编辑的文本文件 因此当我使用 UTF 8 打开它时 某些字符串中有一些 mojibake 和损坏的字符 哪种脚本语言能够最有效地检测这些损坏的字符 Perl 不是一个选择 我基本上试图找到一种使用脚本扫描文本文件并
  • Laravel 5.1 完成后如何捕获作业队列详细信息?

    在 Laravel 5 1 中 我希望在作业完成时收到通知 并提供有关作业的详细信息 具体来说 user id and customer id 我正在使用Queue after方法中的方法AppServiceProvider作为 Larav
  • 在vba中为图例设置颜色代码

    我在每个工作表中都有数据透视表 我必须对它们进行比较 但每个工作表中图例的颜色都不同 如何设置颜色 例如 如果我的图例条目是 ISO 我希望它始终为 蓝色 如果它是 LAT 我希望它在每张纸中都为 红色 这可以通过操纵来完成Series中的
  • 基类和派生类构造函数的内存分配

    创建派生类对象时首先为哪一个分配空间 是基类构造函数还是派生类构造函数 First 分配 您所询问的内存保留不同于并且先于初始化 执行构造函数 本质上在该内存中设置合适的值 以及 正式的 我们的神圣标准 和实践的不同之处在于大多数派生对象的
  • 在多线程场景中正确锁定 List

    好吧 我只是无法正确理解多线程场景 抱歉再次问类似的问题 我只是在互联网上看到许多不同的 事实 public static class MyClass private static List