Правильно блокируя Список <T> в Сценариях MultiThreaded?

установите 32-разрядный libralies.

$ sudo apt-get install ia32-libs-gtk

, если можно выполнить туннель, но трафик не проходит туннель.

можно попробовать это примечание в Facebook.

https://www.facebook. com/notes/%E5%B7%9D%E7%AB%AF-%E8%8B%B1%E6%8F%AE/gettin-to-use-forticlient-on-64-bit-linux-system-64-bit-linux-%E3%81%A7%EF%BD%86%EF%BD%8F%EF%BD%92%EF%BD%94%EF%BD%89%EF%BD%83%EF%BD%8C%EF%BD%89%EF%BD%85%EF%BD%8E%EF%BD%94%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9/410366692372497

я выздоравливаю на человечности 12.10 (x64)

24
задан Community 23 May 2017 в 10:29
поделиться

5 ответов

Здесь я заблокирую сам _myList, поскольку он является частным, но более распространено использование отдельной переменной. Чтобы улучшить несколько моментов:

public static class MyClass 
{
    private static List<string> _myList = new List<string>;
    private static bool _record; 

    public static void StartRecording()
    {
        lock(_myList)   // lock on the list
        {
           _myList.Clear();
           _record = true;
        }
    }

    public static IEnumerable<string> StopRecording()
    {
        lock(_myList)
        {
          _record = false;
          // Return a Read-Only copy of the list data
          var result = new List<string>(_myList).AsReadOnly();
          _myList.Clear();
          return result;
        }
    }

    public static void DoSomething()
    {
        lock(_myList)
        {
          if(_record) _myList.Add("Test");
        }
        // More, but unrelated actions
    }
}

Обратите внимание, что этот код использует блокировку (_myList) для синхронизации доступа к _myList и _record. И вам необходимо синхронизировать все действия с этими двумя.

И, чтобы согласиться с другими ответами здесь, lock (_myList) ничего не делает с _myList, он просто использует _myList как токен (предположительно как ключ в HashSet). Все методы должны действовать честно, запрашивая разрешение с использованием одного и того же токена. Метод в другом потоке все еще может использовать _myList без предварительной блокировки, но с непредсказуемыми результатами.

Мы можем использовать любой токен, поэтому мы часто создаем его специально:

private static object _listLock = new object();

А затем вместо этого используем lock (_listLock) блокировки (_myList) везде.

32
ответ дан 28 November 2019 в 22:51
поделиться

Создание новой блокировки в DoSomething () было бы определенно неправильно - это было бы бессмысленно, поскольку каждый вызов DoSomething () будет использовать другую блокировку. Вы должны использовать вторую форму, но с инициализатором:

private static object _lock = new object();

Это правда, что блокировка не мешает ничему другому получить доступ к вашему списку, но если вы не открываете список напрямую, это не имеет значения: больше ничего не будет доступ к списку в любом случае.

Да, вы можете заключить Start / StopRecording в блокировки таким же образом.

Да, установка логической переменной является атомарной, но это не делает ее потокобезопасной. Если вы обращаетесь к переменной только в пределах одной блокировки, вы в порядке с точки зрения атомарности и изменчивости. В противном случае вы можете увидеть "устаревшие" значения - например,

15
ответ дан 28 November 2019 в 22:51
поделиться

Есть несколько способов заблокировать список. Вы можете заблокировать _myList напрямую при условии, что _myList никогда не будет изменен для ссылки на новый список.

lock (_myList)
{
    // do something with the list...
}

Вы можете создать объект блокировки специально для этой цели.

private static object _syncLock = new object();
lock (_syncLock)
{
    // do something with the list...
}

Если статическая коллекция реализует интерфейс System.Collections.ICollection ( List (T) делает), вы также можете синхронизировать с помощью свойства SyncRoot.

lock (((ICollection)_myList).SyncRoot)
{
    // do something with the list...
}

Главное, что нужно понять, это то, что вы хотите one и только один объект для использования в качестве блокировки sentinal, поэтому создание сигнального сообщения блокировки внутри функции DoSomething () не сработает. Как сказал Джон, каждый поток, вызывающий DoSomething (), получит свой собственный объект, поэтому блокировка этого объекта будет успешной каждый раз и предоставит немедленный доступ к списку. Сделав объект блокировки статическим (через сам список,

7
ответ дан 28 November 2019 в 22:51
поделиться

Первый способ - неверный , поскольку каждый вызывающий абонент блокирует другой объект. Вы можете просто заблокировать список.

lock(_myList)
{
   _myList.Add(...)
}
3
ответ дан 28 November 2019 в 22:51
поделиться

Вы можете неверно истолковать этот ответ , на самом деле утверждается, что оператор lock на самом деле не блокирует объект, о котором идет речь. изменен, скорее это предотвращает выполнение любого другого кода, использующего этот объект в качестве источника блокировки.

На самом деле это означает, что когда вы используете тот же экземпляр в качестве объекта блокировки, код внутри блока блокировки не должен выполняться.

По сути, вы на самом деле не пытаетесь «заблокировать» свой список, вы пытаетесь иметь общий экземпляр, который можно использовать в качестве ориентира, когда вы хотите изменить свой список, когда он используется или «заблокирован» "вы хотите предотвратить выполнение другого кода, который потенциально мог бы изменить список.

1
ответ дан 28 November 2019 в 22:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: