Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么是';线程安全';对象_C#_Multithreading_Collections - Fatal编程技术网

C# 什么是';线程安全';对象

C# 什么是';线程安全';对象,c#,multithreading,collections,C#,Multithreading,Collections,我在C#collection中使用了generic queue,每个人都说最好使用System.collection.generic.queue对象,因为线程安全 请告知使用队列对象的正确决定,以及它如何是线程安全的?可以从多个线程安全地访问线程安全的类型,而无需考虑并发性。这通常意味着该类型是只读的 有趣的是,Queue不是线程安全的-只要队列没有被修改,它就可以支持并发读取,但这与线程安全不同 为了考虑线程安全性,考虑如果两个线程正在访问队列< /代码>会发生什么,第三个线程出现,并开始添加

我在C#collection中使用了generic queue,每个人都说最好使用System.collection.generic.queue对象,因为线程安全


请告知使用队列对象的正确决定,以及它如何是线程安全的?

可以从多个线程安全地访问线程安全的类型,而无需考虑并发性。这通常意味着该类型是只读的

有趣的是,
Queue
不是线程安全的-只要队列没有被修改,它就可以支持并发读取,但这与线程安全不同

为了考虑线程安全性,考虑如果两个线程正在访问<代码>队列< /代码>会发生什么,第三个线程出现,并开始添加或从该代码>删除队列< /代码>。由于此类型不限制此行为,因此它不是线程安全的。

“线程安全”是一个有点不幸的术语,因为它实际上没有可靠的定义。基本上,这意味着当通过多个线程对对象进行操作时,可以保证对象上的某些操作的行为是合理的

考虑最简单的例子:计数器。假设有两个线程正在递增计数器。如果事件顺序发生变化:

  • 线程1从计数器读取,获取 零
  • 线程2从计数器读取,获取 零
  • 线程1递增0,写入 一个要反击
  • 线程两个增量为零,写入 一个要反击
然后注意计数器是如何“丢失”一个增量的。计数器上的简单增量操作不是线程安全的;要使其线程安全,可以使用锁或联锁增量

与队列类似。非线程安全队列可能“丢失”队列,就像非线程安全计数器可能丢失增量一样。更糟糕的是,如果在多线程场景中使用不当,非线程安全队列甚至可能崩溃或产生疯狂的结果

“线程安全”的困难在于它没有明确定义。它仅仅意味着“不会崩溃”吗?这是否意味着会产生合理的结果?例如,假设您有一个“threadsafe”集合。这个代码正确吗

if (!collection.IsEmpty) Console.WriteLine(collection[0]);
不。即使集合是“线程安全的”,也不意味着此代码是正确的;另一个线程可能在检查之后但在写线之前使集合为空,因此,即使该对象据称是“线程安全”的,该代码也可能崩溃。实际上,确定每个相关的操作组合都是线程安全的是一个极其困难的问题


现在来谈谈您的实际情况:任何告诉您“应该使用队列类,因为它是线程安全的,所以更好”的人可能都不清楚他们在说什么。首先,队列不是线程安全的。其次,如果您只在单个线程上使用对象,那么队列是否是线程安全的完全无关!如果有一个集合要在多个线程上访问,那么,正如我在上面的示例中所指出的,无论集合本身是否“线程安全”,都有一个极其困难的问题要解决。您必须确定对集合执行的每个操作组合也是线程安全的。这是一个非常困难的问题,如果是您面临的问题,那么您应该在这个困难的主题上使用专家的服务。

在处理多线程时,您通常必须处理并发性问题。术语“并发性问题”指的是由于在双方共享的资源上交错来自两个不同执行上下文的指令的可能性而特别引入的问题。这里,就线程安全而言,执行上下文是进程中的两个线程;然而,在相关主题中,它们可能是过程

实施螺纹安全措施主要是为了实现两个目标。首先是重新确定线程上下文切换(由操作系统控制,因此在用户级程序中基本不确定)时会发生什么,以防止某些任务完成一半或两个上下文逐个写入内存中的同一位置。大多数措施只是使用少量硬件支持的指令等,以及软件级别的指令,强制所有其他执行上下文远离某个数据类型,而另一个执行上下文正在执行不应中断的工作


通常,只读对象是线程安全的。许多对象不是只读的,如果中间没有修改对象,则可以在没有问题的情况下多个线程发生数据访问(只读)。但这不是线程安全。线程安全是指对一个数据类型执行各种操作,以防止一个线程对其进行的任何修改导致数据损坏或死锁,即使在处理多个并发读写时也是如此。

+1为可靠的专家证词。您还正确地指出,“线程安全”是一个相当模糊的概念。我喜欢每个线程安全相关的问题都由同一个家伙来回答,我已经读了大约2个小时了。这就是硬件锁指令的目的。在整个RMW操作期间,只有一个内核可以拥有缓存线。第一个为锁请求L3缓存片的内核被批准,这会导致它向其他内核发送invalidates,并且在该内核解锁之前,其他内核无法RFO(我认为它拒绝了请求。手册中的模糊内存)还有为什么其他答案说并发。这是平行性