How to identify critical sections in C#?

时间:2018-09-18 20:36:00

标签: c# multithreading critical-section

EDIT:This is not the same thing as the post "CRITICAL_SECTION in c#" as suggested by someone else. This post is about how to identify code that needs to be done in a critical section. The suggested duplicate post is asking about how to use the Windows OS API for critical sections. Not even close to the same.

Learning about multi-threading and async code. Struggling a bit with identifying critical sections. Not really sure what is shared and what is exclusive between context switches. Difference between how value types and reference types are handled. Whether a local variable vs. external variable vs. a parameter passed in is handled in a method.

Below is some code just specifically for this exercise. Assume there are multiple threads that can call into the method with different parameter values. I also added a couple variables external to the method too.

First lets see if some assumptions are correct. CS is "critical section" for convenience.

  1. ++localX needs to be in a CS since it is a local variable. int localX = 0 is ok because this is atomic in C#. i.e. a thread won't set localX back to 0 for another thread when it initially declares the variable.
  2. ++externalX needs to be in a CS since it is a shared resource. And needs to be declared volatile or a thread might act on a cached value and end up with the wrong result.
  3. externalParms.Add( parms[0] ); needs to be in a CS since the Add method is not thread safe and it is a shared resource. Should also be declared volatile.
  4. myList[localX] = externalX; needs to be in a CS since the indexer is not thread safe and it is a local variable.

Questions

  1. What about the ADO.NET code?
    • using (var command = new SqlCommand(spName, connection)) Do I need to worry about a thread putting its spName into another threads command object?
    • command.Parameters.AddRange(parms); I'm adding values to a collection. This is not threadsafe and needs to be in a CS?
    • await command.ExecuteNonQueryAsync(); command is a local variable. Documentation doesn't say anything about the ExecuteNonQueryAsync() method being threadsafe. CS or no CS?
  2. parms[0].Value = rnum; needs to be in a CS?

Arbitrary code:

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] );
}

1 个答案:

答案 0 :(得分:0)

我认为您感到困惑和思考过多。

任何基于“堆栈”的变量(即局部变量)都是“每个线程”的,因此无需为其锁定任何内容,每个线程将具有一个完全独立的线程。

如果您担心多个线程将访问r":-?[()]|([^A-Za-z0-9(),!?'`])",请使用为此目的而创建的集合之一:https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/