Это правильная синхронная конструкция? - PullRequest
0 голосов
/ 28 сентября 2010

У меня многопоточное приложение.Потоки используют ABC.Connector.Я хочу, чтобы только один поток одновременно имел доступ к свойству Connector.

class ABC
{
    /// <summary>
    /// Synchronization object.
    /// </summary>
    static object _syncObject = new object();

    static DataAccess _connector;
    /// <summary>
    /// Global object for data access.
    /// </summary>
    public static DataAccess Connector
    {
        get
        {
            lock (_syncObject)
            {
                return _connector.CreateCopy(); // get a copy of original _connector
            }
        }
        set
        {
            lock (_syncObject)
            {
                _connector = value;
            }
        }
    }
}

Это правильно?

Ответы [ 2 ]

1 голос
/ 28 сентября 2010

Да, это в целом правильно. Но учтите, что после того, как Connector get возвращает ссылку _connector, доступ к ней не синхронизируется.

1 голос
/ 28 сентября 2010

Что ж, это определенно сделает получение и установку свойства Connector поточно-безопасным (хотя я бы сделал _syncObject только для чтения). Однако это не делает DataAccess поточно-безопасным ... мьютекс будет применяться только , пока потоки получают и устанавливают свойство .

Другими словами, если обе темы выполняют:

ABC.DataAccess.DoSomeLongRunningOperation();

, тогда DoSomeLongRunningOperation() будет по-прежнему выполняться одновременно двумя потоками. Если эта операция не является поточно-ориентированной, она все равно будет проблемой.

Если вы хотите, чтобы только один поток за раз использовал DataAccess, вы могли бы написать:

public static void UseConnector(Action<DataAccess> action)
{
    lock (_syncObject)
    {
        action(_connector);
    }
}

Тогда, если два потока оба делают:

ABC.UseConnector(access => access.DoLongRunningOperation());

, тогда DoLongRunningOperation() будет работать только в одном потоке за раз. У вас все еще есть проблема, которую плохо ведущие клиенты могут написать:

DataAccess naughty = null;
ABC.UseConnector(access => naughty = access);
// Haha! I've circumvented your thread safety!
naughty.DoLongRunningOperation();

... но, надеюсь, это не проблема для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...