简体   繁体   English

在 c# 中使用 Interlocked 生成线程安全 ID

[英]Thread safe id generation with Interlocked in c#

I am trying to understand Interlocked in C# in thread synchronization.我试图在线程同步中了解Interlocked in C#。

public int MethodUsedByMultipleThreads()
{
    var id = CreateNextId();
    return id;
}

private long CreateNextId()
{
    long id = 0;
    Interlocked.Exchange(ref id , this._nextId);
    Interlocked.Increment(ref this._nextId);
    return id;
}

Is the line是线

Interlocked.Exchange(ref id , this._nextId);

redundant if I directly use如果我直接使用是多余的

Interlocked.Increment(ref this._nextId);
return _nextId;

Will it serve the same purpose?它会起到同样的作用吗?

The line线

Interlocked.Exchange(ref id, this._nextId);

is both redundant and incorrect.既多余又不正确。 It is redundant because it is practically the same as:它是多余的,因为它实际上与以下内容相同:

id = this._nextId

...because the id is a local variable that is not shared with other threads. ...因为id是一个不与其他线程共享的局部变量。 And it is incorrect because there is a race condition between incrementing the _nextId field and returning it from the method CreateNextId() .这是不正确的,因为在递增_nextId字段和从方法CreateNextId()返回它之间存在竞争条件。 The correct implementation is:正确的实现是:

private long CreateNextId()
{
    long id;
    id = Interlocked.Increment(ref this._nextId) - 1;
    return id;
}

...or simply: ...或者简单地说:

private long CreateNextId() => Interlocked.Increment(ref this._nextId) - 1;

The method Interlocked.Increment increments the _nextId field, and returns the incremented value as an atomic operation. Interlocked.Increment方法递增_nextId字段,并将递增的值作为原子操作返回。

The subtraction - 1 is there to preserve the semantics of your existing code, regarding the meaning of the field _nextId .减法- 1是为了保留现有代码的语义,关于字段_nextId的含义。 It might be preferable to change its name to _lastId or _idSeed , so that the - 1 can be removed.最好将其名称更改为_lastId_idSeed ,以便可以删除- 1

long CreateNextId() => Interlocked.Increment(ref this._nextId);

This is all you need to generate sequential IDs in a thread-safe manner.这就是以线程安全的方式生成顺序 ID 所需的全部内容。


Do not use _nextId directly in any way: return _nextId is a mistake and will yield unpredictable results in a multithreaded environment - the value might be incremented by other threads after your call to Increment in the current thread.不要以任何方式直接使用_nextIdreturn _nextId是错误的,在多线程环境中会产生不可预知的结果——在当前线程中调用Increment后,该值可能会被其他线程递增。

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

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