Статические свойства в статических классах - PullRequest
6 голосов
/ 13 сентября 2010

Вопрос относительно статических переменных в статических классах.

Если у меня есть статический класс, и я устанавливаю значение свойства, открытого для него, устанавливается ли значение этой переменной для всех экземпляров класса?Таким образом, если поток 1 устанавливает значение свойства в 999, будет ли значение также установлено для потока 2 в 999?

Ответы [ 2 ]

12 голосов
/ 13 сентября 2010

Да, это так.Внутри AppDomain имеется только одна копия полей статического класса.

Однако следует учитывать синхронизацию.Если поток 1 устанавливает (записывает) переменную, а поток 2 читает ее одновременно, вы можете получить неожиданные результаты, потому что вполне возможно, что одна операция записи фактически разделена на несколько инструкций процессора.

Предположим, вы установили значение long.Это 64-битное значение, и для его написания требуется как минимум 2 инструкции процессора (на 32-битной машине).Теоретически возможно, что чтение одной и той же переменной long запланировано между двумя инструкциями записи, что приведет к неожиданному поведению.

2 голосов
/ 13 сентября 2010

Просто чтобы добавить к обсуждению (почему бы и нет?): Да, свойство static является общим для всех экземпляров класса, независимо от потока (если поле поддержки не помечено ThreadStatic, то есть!).Но да, есть потенциальные проблемы с многопоточностью, с которыми вам приходится сталкиваться при работе с такими свойствами.Вот сценарий, к которому, я думаю, другие стремятся.

Рассмотрим этот код:

int x = MyClass.StaticProperty;
MyClass.StaticProperty = x + 1;

Предыдущий пример - очень простой пример того, как из-за состояния гонки два потока могут выполнить то, что есть предполагается, что является двумя неделимыми действиями, но вместо этого фактически оказывается единым действием.

Для иллюстрации:

Thread 1                        Thread 2
int x = MyClass.StaticProperty;                                 // Let's say
                                int x = MyClass.StaticProperty; // this is 1.  
MyClass.StaticProperty = x + 1;                                 // OK, so x is
                                MyClass.StaticProperty = x + 1; // now... 2.

Видите ли вы проблему?Оба потока могут оба прочитать значение свойства перед тем, как один из них записывает в него;и записываемое в него значение зависит от прочитанного значения, которое было одинаковым для обоих потоков!

В простых сценариях, подобных приведенному выше, в * есть удобный класс1025 * пространство имен, которое может сделать многопоточное чтение / запись довольно безболезненным для реализации: Interlocked.Например, для увеличения на StaticProperty выше потокобезопасным способом вы можете обновить MyClass следующим образом:

class MyClass
    static int _staticProperty;
    public static int StaticProperty
    {
        get { return _staticProperty; }
    }

    public static int IncrementProperty()
    {
        // increments _staticProperty ATOMICALLY
        // and returns its previous value
        return Interlocked.Increment(_staticProperty);
    }
}

В более сложных сценариях (т. Е. Когда вы не просто изменяете простые числовые поляпростым способом) вам может потребоваться разработать собственную стратегию синхронизации, наиболее распространенной из которых является наличие назначенного объекта блокировки и просто lock на нем для каждой операции, которую вы хотите вести атомарно.

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