Аннулирование ссылки на объект, пока другой поток выполняет над ней метод (.NET)
-
18-09-2019 - |
Вопрос
(Меня интересует среда .NET CLR)
Что именно происходит, когда один поток изменяет объект, на который ссылается переменная, в то время как другой поток выполняет метод для исходного объекта?
Например, скажем, тип Foo
имеет переменную 'Bar' типа Bar
, и Bar
не имеет состояния на уровне класса (по крайней мере, на данный момент я хотел бы сохранить этот сценарий простым):
// Thread 1
foo.Bar = new Bar();
foo.Bar.SomeMethod();
В то же время, прежде чем это завершит выполнение ...
// Thread 2
foo.Bar = new Bar();
Что происходит с методом, который выполняется (был?) в потоке 1?Все ли, что ему нужно для завершения, уже есть в стеке?
Меняет ли это ситуацию, если поток 2 делает это вместо этого?
foo.Bar = null;
Решение
Если вызов гарантированно уже находится внутри SomeMethod()
, тогда ничего необычного не произойдет - this
является неявным аргументом для методов, поэтому он никогда не будет использовать значение поля (или свойства, каким бы оно ни было) напрямую.
Можете ли вы действительно гарантировать это - другой вопрос.
Другие советы
-- редактировать:исправлено сбивающее с толку предложение.
Ну, на самом деле присвоение переменной будет атомарным, поэтому не похоже, что вызов внезапно осознает "о боже, я равен null!" во время выполнения .someMethod()
Что может однако случается так, что foo.Bar.someMethod() сам по себе вызываться не будет, потому что поток 2 сначала (возможно) установит для него значение null;таким образом, он просто не будет выполняться (он завершится сбоем с исключением null ref).
То же самое относится и к вашему первому примеру;он просто вызовет .Какой-нибудь метод для нового объекта.
Я думаю, вы думаете, что пока все может измениться .Какой-то метод запущен, верно?Нет.Там ничего не изменится.Он по-прежнему будет иметь контекст самого себя.
Что именно происходит, когда один поток изменяет объект, на который ссылается переменная, в то время как другой поток выполняет метод для исходного объекта?
Что происходит, так это то, что вы переписываете свой код, чтобы должным образом синхронизировать доступ к этим полям.