We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Describe the bug 在:#162 (comment) 中描述了这点,是我自己以前的锅,之后看看如何改吧。
Expected behavior 消除 data race
Additional context Add any other context about the problem here.
The text was updated successfully, but these errors were encountered:
刚在评论里加了点东西,之后为了方便直接贴在这了:
这里应该是一直遗留下来的错误,属于是我当初犯下的错误之一(其实也是照着 THUAI3.0 抄的,但我把这个错误发扬光大了 x)。写操作加锁读操作却不加锁的情况下,这个锁是无意义的。主要有以下三种解决方案:
读写都加锁,即读的时候也锁起来(但是开销较大)
读写全不加锁,在外面加(不推荐,会很麻烦)
使用原子操作(最推荐,但原子操作坑较多,不好把握,而且由于当前这种是凑合能连续两年跑起来的,改了之后说不定会出现什么连锁 bug):
private int canOpen = 0; private bool CanOpen { get => Interlocked.CompareExchange(ref canOpen, 0, 0) != 0; set => Interlocked.Exchange(ref canOpen, value ? 1 : 0); }
有几个问题需要注意:
bool
Interlocked
int
0
Read
Write
CompareExchange
Exchange
有趣的是,微软声称对小于计算机字长的类型(例如 int)的直接操作都是原子的,所以不需要 Interlocked 操作,但是,例如 在这个回答当中,把里面的 double 都改成 int,在 update_variable 执行后 Sleep 足够长时间再打印 myVar2,使用 .NET 6 Release 编译运行,结果发现 myVar2 的值始终是 0!说明编译器优化过程中直接优化掉了对 myVar2 的反复赋值,或优化掉对其的读取等等,总之没有考虑原子性。说明微软文档所作的保证,不可靠!!!——不要相信微软的鬼话!!!(但更神奇的是,在 .NET 7 Release 上运行居然是结果正确的???) 刚发现一个更简单的例子: int i = 0; new Thread(() => { Thread.Sleep(1000); i = 1; }) { IsBackground = true }.Start(); while (i == 0) ; 上述代码在 .NET 6 Release 会导致死循环(.NET 7 Release 竟然不会死循环),这说明对 i 的操作至少在 .NET 6 上并不是原子的!
有趣的是,微软声称对小于计算机字长的类型(例如 int)的直接操作都是原子的,所以不需要 Interlocked 操作,但是,例如 在这个回答当中,把里面的 double 都改成 int,在 update_variable 执行后 Sleep 足够长时间再打印 myVar2,使用 .NET 6 Release 编译运行,结果发现 myVar2 的值始终是 0!说明编译器优化过程中直接优化掉了对 myVar2 的反复赋值,或优化掉对其的读取等等,总之没有考虑原子性。说明微软文档所作的保证,不可靠!!!——不要相信微软的鬼话!!!(但更神奇的是,在 .NET 7 Release 上运行居然是结果正确的???)
double
update_variable
Sleep
myVar2
刚发现一个更简单的例子:
int i = 0; new Thread(() => { Thread.Sleep(1000); i = 1; }) { IsBackground = true }.Start(); while (i == 0) ;
上述代码在 .NET 6 Release 会导致死循环(.NET 7 Release 竟然不会死循环),这说明对 i 的操作至少在 .NET 6 上并不是原子的!
i
Sorry, something went wrong.
由于不少变量都是相关联的,最后我是决定采用多数直接读写均加锁,部分读写锁,少量原子操作的方式
shangfengh
No branches or pull requests
Describe the bug
在:#162 (comment) 中描述了这点,是我自己以前的锅,之后看看如何改吧。
Expected behavior
消除 data race
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: