如何识别 C# 中的关键部分?

How to identify critical sections in C#?

编辑:这与其他人建议的 post "CRITICAL_SECTION in c#" 不同。这个post是关于如何识别需要在关键部分完成的代码。建议的副本 post 询问如何将 Windows OS API 用于关键部分。甚至不一样。

学习多线程和异步代码。在识别关键部分时遇到一些困难。不太确定上下文切换之间共享的内容和独占的内容。值类型和引用类型的处理方式之间的差异。局部变量vs.外部变量vs.传入的参数是否在一个方法中处理。

下面是一些专门用于此练习的代码。假设有多个线程可以调用具有不同参数值的方法。我还在方法之外添加了几个变量。

首先让我们看看一些假设是否正确。 CS是"critical section"为了方便。

  1. ++localX 需要在 CS 中,因为它是一个局部变量。 int localX = 0 没问题,因为这在 C# 中是原子的。即,一个线程在初始声明变量时不会将另一个线程的 localX 设置回 0
  2. ++externalX 需要在 CS 中,因为它是共享资源。并且需要声明为 volatile,否则线程可能会作用于缓存的值并最终得到错误的结果。
  3. externalParms.Add( parms[0] ); 需要在 CS 中,因为 Add 方法不是线程安全的,它是共享资源。也应该声明为 volatile。
  4. myList[localX] = externalX; 需要在 CS 中,因为索引器不是线程安全的,而且它是一个局部变量。

问题

  1. ADO.NET代码呢?
    • using (var command = new SqlCommand(spName, connection)) 我是否需要担心线程将其 spName 放入另一个线程 command 对象?
    • command.Parameters.AddRange(parms); 我正在向集合中添加值。这不是线程安全的,需要在 CS 中?
    • await command.ExecuteNonQueryAsync(); command 是局部变量。文档没有说明 ExecuteNonQueryAsync() 方法是线程安全的。 CS 还是没有 CS?
  2. parms[0].Value = rnum; 需要在 CS 中吗?

任意码:

int externalX = 10;
List<SqlParameter> externalParms = new List<SqlParameter>();
internal async Task SampleExecuteNonQueryAsync(string spName, SqlParameter[] parms)
{
    int localX = 0;
    List<int> myList = new List<int>() { -1,-1};
    Random rnd = new Random();

    using (var connection = new SqlConnection(_connString))
    {
        await connection.OpenAsync();
        using (var command = new SqlCommand(spName, connection))
        {
            ++localX;
            int rnum = rnd.Next(1, 100);
            parms[0].Value = rnum;

            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.AddRange(parms);
            await command.ExecuteNonQueryAsync();

            ++externalX;                    
        }
    }
    myList[localX] = externalX;
    externalParms.Add( parms[0] );
}

我觉得你很糊涂,想太多了。

任何基于 'stack' 的变量(即局部变量)都是 'per-thread',因此不需要为它们锁定任何东西,每个线程都有一个完全独立的线程。

如果您担心超过 1 个线程将访问 externalParms,请使用为此目的制作的集合之一:https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/