Properly locking a List in MultiThreaded Scenarios?

前端 未结 5 1709
难免孤独
难免孤独 2020-11-30 08:52

Okay, I just can\'t get my head around multi-threading scenarios properly. Sorry for asking a similar question again, I\'m just seeing many different \"facts\" around the in

5条回答
  •  南方客
    南方客 (楼主)
    2020-11-30 09:28

    I will lock on the _myList itself here since it is private, but using a separate variable is more common. To improve on a few points:

    public static class MyClass 
    {
        private static List _myList = new List;
        private static bool _record; 
    
        public static void StartRecording()
        {
            lock(_myList)   // lock on the list
            {
               _myList.Clear();
               _record = true;
            }
        }
    
        public static IEnumerable StopRecording()
        {
            lock(_myList)
            {
              _record = false;
              // Return a Read-Only copy of the list data
              var result = new List(_myList).AsReadOnly();
              _myList.Clear();
              return result;
            }
        }
    
        public static void DoSomething()
        {
            lock(_myList)
            {
              if(_record) _myList.Add("Test");
            }
            // More, but unrelated actions
        }
    }
    

    Note that this code uses lock(_myList) to synchronize access to both _myList and _record. And you need to sync all actions on those two.

    And to agree with the other answers here, lock(_myList) does nothing to _myList, it just uses _myList as a token (presumably as key in a HashSet). All methods must play fair by asking permission using the same token. A method on another thread can still use _myList without locking first, but with unpredictable results.

    We can use any token so we often create one specially:

    private static object _listLock = new object();
    

    And then use lock(_listLock) instead of lock(_myList) everywhere.

    This technique would have been advisable if myList had been public, and it would have been absolutely necessary if you had re-created myList instead of calling Clear().

提交回复
热议问题