具有易失性或锁定性的财产 [英] Property with Volatile or Lock
问题描述
我有一个带有后备字段的属性,我想使线程安全(获取并设置). 除了设置和返回之外,get and set方法没有逻辑.
I have a property with a backing field which I want to make thread safe (get and set). The get and set method has no logic except the setting and returning.
我认为有两种方法可以将逻辑封装在属性self中(易失性和锁定). 我对这两者的理解是正确的还是犯错了?
I think there are two ways to capsule the logic in the property self (volatile and lock). Is my understanding of the two's correct or have I make any mistakes?
下面是我的示例:
public class ThreadSafeClass
{
// 1. Volatile Example:
private volatile int _processState_1;
public int ProcessState_1
{
get { return _processState_1; }
set { _processState_1 = value; }
}
// 2. Locking Example:
private readonly object _processState_2Lock = new object();
private int _processState_2;
public int ProcessState_2
{
get
{
lock (_processState_2Lock)
{
return _processState_2;
}
}
set
{
lock (_processState_2Lock)
{
_processState_2 = value;
}
}
}
}
推荐答案
有关更多信息,请参见 J.Albahari的绝佳站点:
For mor information see the great site by J. Albahari:
同步结构可以分为四类:
Synchronization constructs can be divided into four categories:
简单的阻止方法:
这些等待另一个线程完成或等待一段时间. Sleep
,Join
和Task.Wait
是简单的阻止方法.
These wait for another thread to finish or for a period of time to elapse. Sleep
, Join
, and Task.Wait
are simple blocking methods.
锁定结构:
这些限制了一次可以执行某些活动或执行一段代码的线程数.排它锁定结构是最常见的-一次仅允许一个线程,并且允许竞争线程访问公共数据而不会互相干扰.标准排它锁定构造为lock
(Monitor.Enter
/Monitor.Exit
),Mutex
和SpinLock
.非唯一的locking
构造是Semaphore
,SemaphoreSlim
和reader/writer
锁.
These limit the number of threads that can perform some activity or execute a section of code at a time. Exclusive locking constructs are most common — these allow just one thread in at a time, and allow competing threads to access common data without interfering with each other. The standard exclusive locking constructs are lock
(Monitor.Enter
/Monitor.Exit
), Mutex
, and SpinLock
. The nonexclusive locking
constructs are Semaphore
, SemaphoreSlim
, and the reader/writer
locks.
信令构造:
这允许线程暂停直到接收到来自另一个线程的通知为止,从而避免了低效率的轮询.常用的信号设备有两种:事件等待句柄和监视器的等待/脉冲方法. Framework 4.0引入了CountdownEvent
和Barrier
类.
These allow a thread to pause until receiving a notification from another, avoiding the need for inefficient polling. There are two commonly used signaling devices: event wait handles and Monitor’s Wait/Pulse methods. Framework 4.0 introduces the CountdownEvent
and Barrier
classes.
无阻塞同步结构:
这些通过调用处理器原语来保护对公共字段的访问. CLR和C#提供以下非阻塞构造:Thread.MemoryBarrier
,Thread.VolatileRead
,Thread.VolatileWrite
,volatile
关键字和Interlocked
类.
These protect access to a common field by calling upon processor primitives. The CLR and C# provide the following nonblocking constructs: Thread.MemoryBarrier
, Thread.VolatileRead
, Thread.VolatileWrite
, the volatile
keyword, and the Interlocked
class.
volatile
关键字:
The volatile
keyword:
volatile关键字指示编译器在对该字段的每次读取中生成一个获取围栏,并在对该字段的每次写入中生成一个释放围栏.获取栅栏可防止其他读取/写入在栅栏之前移动;释放栅栏可防止其他读取/写入在栅栏之后移动.这些半栅栏"比完整的栅栏要快,因为它们为运行时和硬件提供了更大的优化范围.
The volatile keyword instructs the compiler to generate an acquire-fence on every read from that field, and a release-fence on every write to that field. An acquire-fence prevents other reads/writes from being moved before the fence; a release-fence prevents other reads/writes from being moved after the fence. These "half-fences" are faster than full fences because they give the run-time and hardware more scope for optimization.
碰巧的是,英特尔的X86和X64处理器始终将获取栅栏应用于读取,将释放栅栏应用于写入(无论是否使用volatile关键字),因此,如果您使用这些关键字,则此关键字对硬件没有任何影响处理器.但是,
volatile
确实会影响编译器和CLR以及64位AMD和(在更大程度上)Itanium处理器执行的优化.这意味着,依靠您的客户端运行特定类型的CPU,您再也无法放心了.
As it happens, Intel’s X86 and X64 processors always apply acquire-fences to reads and release-fences to writes — whether or not you use the volatile keyword — so this keyword has no effect on the hardware if you’re using these processors. However,
volatile
does have an effect on optimizations performed by the compiler and the CLR — as well as on 64-bit AMD and (to a greater extent) Itanium processors. This means that you cannot be more relaxed by virtue of your clients running a particular type of CPU.
将volatile应用于字段的效果可总结如下:
The effect of applying volatile to fields can be summarized as follows:
First instruction Second instruction Can they be swapped?
Read Read No
Read Write No
Write Write No (The CLR ensures that write-write operations are never swapped, even without the volatile keyword)
Write Read Yes!
请注意,应用volatile并不会阻止写入和读取之间的交换,这可能会引起脑筋急转弯. Joe Duffy通过以下示例很好地说明了此问题:如果Test1
和Test2
在不同的线程上同时运行,则a和b的最终值都可能为0(尽管在y
):
Notice that applying volatile doesn’t prevent a write followed by a read from being swapped, and this can create brainteasers. Joe Duffy illustrates the problem well with the following example: if Test1
and Test2
run simultaneously on different threads, it’s possible for a and b to both end up with a value of 0 (despite the use of volatile on both x
and y
):
class IfYouThinkYouUnderstandVolatile
{
volatile int x, y;
void Test1() // Executed on one thread
{
x = 1; // Volatile write (release-fence)
int a = y; // Volatile read (acquire-fence)
...
}
void Test2() // Executed on another thread
{
y = 1; // Volatile write (release-fence)
int b = x; // Volatile read (acquire-fence)
...
}
}
MSDN文档指出,使用volatile关键字可确保始终在字段中提供最新值.这是不正确的,因为正如我们所看到的,写入和读取之后可以重新排序.
The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered.
这为避免出现波动提供了一个强有力的案例:即使您理解了此示例中的精妙之处,其他从事您代码工作的开发人员也会理解吗? Test1
和Test2
中的两个分配之间的完全隔离(或锁定)可以解决此问题.
This presents a strong case for avoiding volatile: even if you understand the subtlety in this example, will other developers working on your code also understand it? A full fence between each of the two assignments in Test1
and Test2
(or a lock) solves the problem.
传递引用参数或捕获的局部变量不支持volatile
关键字:在这种情况下,您必须使用VolatileRead
和VolatileWrite
方法.
The volatile
keyword is not supported with pass-by-reference arguments or captured local variables: in these cases you must use the VolatileRead
and VolatileWrite
methods.
这篇关于具有易失性或锁定性的财产的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!