Отказ от ответственности: этот код работает два потока непрерывно навсегда. Запускайте на свой страх и риск.
using System;
using System.Threading.Tasks;
namespace ConsoleApp126
{
internal class AnyClass
{
private int _state;// = 0
public AnyClass()
{
_state = 1;
}
~AnyClass()
{
_state = 2;
}
public void TestState()
{
if (_state != 1)
throw new Exception("Already finalized");
}
}
internal class Tester
{
private AnyClass _any = new AnyClass();
private object _sync = new object();
public void Initialize()
{
//lock(_sync)
_any = new AnyClass();
GC.Collect();
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
}
public void Test()
{
AnyClass any;
//lock (_sync)
any = _any;
// mov eax,dword ptr [ebp-3Ch]
// mov eax, dword ptr[eax + 4] // What if a context switch happens after this instruction?
// mov dword ptr[ebp - 40h], eax
any.TestState();
}
}
class Program
{
static void Main(string[] args)
{
var tester = new Tester();
Task.Run(() =>
{
try
{
while (true)
tester.Initialize();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
Task.Run(() =>
{
try
{
while (true)
tester.Test();
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
Console.ReadLine();
}
}
}
Безопасно ли назначать и получать ссылку на объект из нескольких потоков без кода синхронизации?
Если в обоих случаях оператор блокировки (_syn c) не должен быть прокомментирован для обеспечения безопасности сборки мусора?
Если нет, что произойдет, если после переключения контекста «mov eax, dword ptr [eax + 4]» и G C собирает объект, на который ссылается eax. Тогда, когда "mov dword ptr [ebp - 40h], eax", наконец, присваивает ссылку на объект переменной "any", не может ли ссылка быть недействительной? Я запустил код в течение 12 часов без блокировки и не заметил плохого поведения. Может кто-нибудь объяснить, как это работает?
Я использовал VS2017 на Windows 10 1909. Targeted. NET 4.71 и x86.