2010-09-13 3 views
6

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

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

ответ

11

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

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

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

+3

Строго, нет * экземпляра * статического класса, но есть одна копия каждого статического поля. –

+0

Вы правы. Спасибо за дополнительную информацию. Я обновил свой ответ. –

+0

@Marc: Да, но ... OP * did * say (confusingly), "является ли значение этой переменной для всех экземпляров класса?«Поэтому я предполагаю, что OP фактически имеет только обычный класс и говорит о статическом свойстве. Либо это, либо неправильно использовало слово« экземпляры ». –

2

Просто чтобы добавить к обсуждению (почему бы и нет?): Да, свойство 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. 

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

В простых сценариях, как один из приведенной выше, есть удобный класс предоставляется в System.Threading имен, которые могут сделать многопоточное чтение/запись достаточно безболезненно осуществить: 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 для каждой операции, которую вы хотите вести атомарно.