简体   繁体   English

.NET线程 - 分配需要锁定

[英].NET Threading - is lock needed for assignments

I've got some multi threaded code I'd like to increase the performace of a bit, so I'm wondering if I can get rid of a lock. 我有一些多线程代码,我想增加一点的性能,所以我想知道我是否可以摆脱锁定。

I've got a field member: 我有一个现场成员:

private IList<ServerStatus> status;

It's updated in a thread like so: 它在这样的线程中更新:

status = GetUpdatedStatus();

And it's used in another thread like this: 它在另一个线程中使用,如下所示:

var currentStatus = status;

So the question is, can the above yield any problems without locks around the two assignment statements ? 所以问题是,如果没有锁定两个赋值语句,上面会产生任何问题吗?

I guess the only scenario I can see is currentStatus being null, but then again I'd expect an assignment to be somewhat thread-safe (either it has changed the reference or not) 我想我能看到的唯一情况是currentStatus为null,但是我再次希望赋值有点线程安全(或者它已经更改了引用)

You are right. 你是对的。 You will see the assignment or you won't see it. 您将看到作业,否则您将看不到它。 Assignments (and reads) of references are always "atomic" (in the end it's because on 32 bits machines references are 32 bits, so can be done atomically, and on 64 bits machines (running a 64 bits app) references are 64 bits, so can be done atomically. The only exception is trying to write/read a long (64 bits) on a 32 bits machine. There you would have to use Interlocked.Read / Interlocked.Exchange) 引用的赋值(和读取)总是“原子的”(最后它是因为32位机器引用是32位,所以可以原子方式完成,而64位机器(运行64位应用程序)引用是64位,所以可以原子方式完成。唯一的例外是尝试在32位机器上写/读长(64位)。你必须使用Interlocked.Read / Interlocked.Exchange)

Normally should declare status as volatile , so that each thread sees only the latest version. 通常应将状态声明为volatile ,以便每个线程只能看到最新版本。 You should read this: http://www.albahari.com/threading/ it's very very good! 你应该读到这个: http//www.albahari.com/threading/它非常好!

If you don't trust me, read the section Do We Really Need Locks and Barriers? 如果您不信任我,请阅读Do We Really Need Locks and Barriers? here http://www.albahari.com/threading/part4.aspx 这里http://www.albahari.com/threading/part4.aspx

Ah... I was forgetting... The world HATES you, so there is a little thing to know of volatile: sometimes it doesn't work :-) :-) Read, in the same page of the other example, the section The volatile keyword , the part UNDER the red box. 啊......我忘记了......世界恨你,所以有一点要知道它的变化:有时它不起作用:-) :-)阅读,在另一个例子的同一页面, section The volatile keyword ,红色框下面的部分。 Notice that applying volatile doesn't prevent a write followed by a read from being swapped, and this can create brainteasers . Notice that applying volatile doesn't prevent a write followed by a read from being swapped, and this can create brainteasers In the end, the only way to be sure is to use Interlocked.Exchange to write and Interlocked.CompareExchange to read something OR protect the read and the write sections with synchronization (like lock ) OR fill your program with Thread.MemoryBarrier (but don't try it, you'll fail, and you won't even know why). 最后,可以肯定的唯一方式是使用Interlocked.Exchange编写和Interlocked.CompareExchange阅读的东西或保护读取和使用同步(如写入部分lock )或Thread.MemoryBarrier填写你的程序(但不要试试看,你会失败,你甚至不知道为什么。 You are guaranteed that all the reads and the writes done in the lock will be done IN the lock, not before or after. 保证锁定中的所有读取和写入都将在锁定中完成,而不是在锁定之前或之后。

Reference writes are guaranteed atomic, so there are only really two things to check: 参考写入是原子保证的,因此只需要检查两件事:

  • usage in a tight loop - might need to add volatile if you need to notice the change 在紧密循环中使用 - 如果需要注意更改,可能需要添加volatile
  • double updates; 双重更新; if you are (for example) doing add/remove via reference swap, you should use Interlocked.CompareExchange to make sure you don't lose data; 如果您(例如)通过引用交换进行添加/删除,则应使用Interlocked.CompareExchange确保不丢失数据; keep reapplying your change until you win the swap 继续重新应用您的更改,直到您赢得交换

ie

object snapshot, newValue;
do
{
    snapshot = field;

    // do something based on that; create a clone
    // with more/less data for example
    newValue = ...;
} while (!ReferenceEquals(
    Interlocked.CompareExchange(ref field, newValue, snapshot), snapshot));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM