Answers:
原子操作是通过使用诸如互斥锁或信号量之类的某种锁来实现线程安全的方法,这些锁在内部使用原子操作,或者通过使用原子和内存栅栏实现无锁同步。
因此,对原始数据类型的原子操作是实现线程安全的工具,但不能自动确保线程安全,因为您通常有多个相互依赖的操作。您必须确保完成这些操作而不会中断,例如使用Mutexes。
是的,用c#编写这些原子数据类型之一是线程安全的,但这并不能使您在线程中使用它们的函数安全。即使第二个线程“同时”访问它,它也只能确保正确执行一次写操作。不管怎样,不能确保从当前线程的下一次读取获得先前写入的值,因为可能已经向另一个线程写入了该值,只是读取的值是有效的。
原子性和线程安全性是两个不同的事物。原子性是指操作的“全有或全无”质量。如果不能100%成功地执行某项操作,则系统应保持在该操作任何部分开始之前的总体状态。典型的例子是数据库事务。保存发票(包括抬头和多个行项目)时,必须成功放置每个数据库行中的每个部分;如果不是,则数据丢失或损坏。如果无法插入订单项,则不仅不应插入剩余的其他行,而且不应保留已处理的任何行。
线程安全性是指事物的组合,包括原子性,它使操作可以“重入”。多个工作人员可以在相同或不同的时间开始执行相同的操作,而不会影响任何其他操作。有许多用于线程安全操作的模型。它们中的大多数在概念上可以归结为完全隔离地运行多个并行任务(两个工作人员可以在两个不同的对象或对象集合上执行同一任务,甚至不知道另一个工作人员是否存在),或者在其中建立“管道”多个工人在整个操作中都执行一个任务(每个工人从第一个任务前进到下一个任务,依此类推,或者专注于一个任务并将其中间的“工作产品”交给下一个工人)。
原子操作是不能中断的操作。
安全线程是可以安全中断的线程。
线程安全性是通过原子操作获得的,尤其是在防止多次访问关键资源的逻辑中。
基本的原子操作是Test-and-set,用于实现信号量,而信号量又用于实现线程安全。