c# - 从多个线程分配和获取对象引用是否需要同步代码?
问题描述
免责声明:此代码永远连续运行两个线程。运行风险自负。
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();
}
}
}
在没有同步代码的情况下从多个线程分配和获取对象引用是否安全?
是否应该在这两种情况下都不要取消注释 lock(_sync) 语句以确保垃圾收集是安全的?
如果不是,如果在“mov eax, dword ptr[eax + 4]”之后有一个上下文切换,并且 GC 收集到 eax 中引用的对象,会发生什么。那么当“mov dword ptr[ebp - 40h], eax”最终将对象引用赋值给变量“any”时,是不是不可能引用无效了?我已经在没有锁的情况下运行了 12 个小时的代码,并且没有观察到任何不良行为。有人可以解释一下这是如何工作的吗?
我在 Windows 10 1909 上使用了 VS2017。针对 .NET 4.71 和 x86。
解决方案
推荐阅读
- django - 502 Bad Gateway nginx 服务器
- c# - 如何将进度消息异步发送到 WPF UI
- webdrivermanager-java - webdrivermanager - 关闭或重新配置控制台日志记录
- jupyter-notebook - 如何在 VS-Code 中输入 Jupyter 风格的代码对齐行为?
- linux - 如何在 Linux/Systemd/Networkd 上启动时启用 VRF
- javascript - 当我使用节点服务器时,我的 css、js 和图像停止工作
- c++ - C++ bool 得到随机/错误的值?
- python-3.x - 更改列表副本的函数
- sympy - 如何打印 sympy 矩阵....为什么要换行?
- junit - 使用 mockito 进行 WebClient GET 单元测试