关于.NET线程的访谈问题

Sup*_*tar 7 multithreading

您能描述两种同步对类成员执行的多线程写访问的方法吗?

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

Jef*_*nal 13

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

public class Number {
    private int a = 0;
    public void Add(int b) {
        a += b;
    }
}
Run Code Online (Sandbox Code Playgroud)

构建它时,您将获得以下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
Run Code Online (Sandbox Code Playgroud)

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

number.Add(2); // Thread 1
number.Add(3); // Thread 2
Run Code Online (Sandbox Code Playgroud)

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

a = 0 + 2; // Thread 1
a = 0 + 3; // Thread 2
Run Code Online (Sandbox Code Playgroud)

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

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

而它被写入1)锁定访问类的成员,使用很多的一个.NET同步原语(如lock,Mutex,ReaderWriterLockSlim,等),以便只有一个线程可以在同一时间进行这项工作.

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

还有其他技术.有些(比如Interlocked)仅限于特定的数据类型,还有更多(比如非阻塞同步Joseph Albahari在C#中的线程的第4部分中讨论的那些),尽管它们更复杂:谨慎处理它们.


Tho*_*rin 12

在多线程应用程序中,有许多情况下同时访问相同的数据可能会导致问题.在这种情况下,需要同步以保证在任何时候只有一个线程可以访问.

我想他们的意思是使用lock-statement(或SyncLock在VB.NET中)而不是使用Monitor.

您可能希望阅读此页面以获取示例并理解该概念.但是,如果您没有使用多线程应用程序设计的经验,如果您的新雇主让您参加测试,很可能会很快显现出来.这是一个相当复杂的主题,有许多可能的陷阱,如死锁.

关于这个主题也有一个不错的MSDN页面.

可能还有其他选项,具体取决于成员变量的类型以及如何更改.例如,可以使用Interlocked .Increment方法来增加整数.

作为问题的练习和演示,尝试编写一个启动5个并发线程的应用程序,每个线程增加一个共享计数器一百万次.计数器的预期最终结果将是500万,但这(可能)不是你最终会得到的结果:)

编辑:自己快速实现(下载).样本输出:

Unsynchronized counter demo:
expected counter = 5000000
actual counter   = 4901600
Time taken (ms)  = 67

Synchronized counter demo:
expected counter = 5000000
actual counter   = 5000000
Time taken (ms)  = 287
Run Code Online (Sandbox Code Playgroud)

  • "C#in Depth"是一本很棒的书. (2认同)