多线程 – 面向.NET线程的访谈问题

您能描述两种同步多线程写访问的方法吗?
在班级成员?

请任何人帮助我这是什么意思,什么是正确的答案.

当您在C#中更改数据时,可能会将看似单个操作的内容编译为多个指令.参加以下课程:

public class Number {
    private int a = 0;
    public void Add(int b) {
        a += b;
    }
}

构建它时,您将获得以下IL代码:

IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  dup
// Pushes the value of the private variable 'a' onto the stack
IL_0003:  ldfld      int32 Simple.Number::a
// Pushes the value of the argument 'b' onto the stack
IL_0008:  ldarg.1
// Adds the top two values of the stack together
IL_0009:  add
// Sets 'a' to the value on top of the stack
IL_000a:  stfld      int32 Simple.Number::a
IL_000f:  ret

现在,假设你有一个Number对象,两个线程调用它的Add方法,如下所示:

number.Add(2); // Thread 1
number.Add(3); // Thread 2

如果您希望结果为5(0 2 3),则表示存在问题.您不知道这些线程何时执行其指令.在执行IL_000a(实际更改成员变量)之前,两个线程都可以执行IL_0003(将零推到堆栈上),然后得到:

a = 0 + 2; // Thread 1
a = 0 + 3; // Thread 2

完成’胜利’的最后一个线程,在过程结束时,a是2或3而不是5.

因此,您必须确保在另一组之前完成一整套指令.为此,您可以:

1)使用众多.NET synchronization primitives中的一个(如lock,Mutex,ReaderWriterLockSlim等)锁定对类成员的访问,以便一次只能有一个线程处理它.

2)将写入操作推送到队列中并使用单个线程处理该队列.正如Thorarin所指出的,如果它不是线程安全的,你仍然必须同步对队列的访问,但是对于复杂的写操作来说它是值得的.

还有其他技术.有些(如Interlocked)仅限于特定的数据类型,甚至更多(如Non-blocking synchronizationPart 4 of Joseph Albahari’s Threading in C#中讨论的那些),尽管它们更复杂:谨慎处理它们.

相关文章
相关标签/搜索