原文 永远不要使用__gshared
.这是明显安全漏洞.改为使用shared
.
如果使用时遇见shared
的编译
错误,那是编译器
在警告你.应该认真考虑
线程安全,然后才在正确的位置抛弃shared
.
使用__gshared
,编译器假装没有看到变量
是共享
的.并除非仔细思考,保证会生成竞争
.
顺便,有优先__gshared
而非shared
的情况吗?似乎许多新手在用__gshared
.
我不完全
同意该点,这仅取决于你用法.一般,你应该使用shared
,但__gshared
有意义.只是在多线程
可更改时才有问题,但如果它仅从单线程
更改但从多线程
读取,则一般不是问题.
总之:
单写/单读?用__gshared
单写/多读?用__gshared
多写/单读?用shared
多写/多读?用shared
如果与C对接,则需要__gshared
.但是,是的,这里应该使用shared
.
__gshared
表现不错,但我优先用std.concurrency
,示例:
所有这些
都可能是竞争条件
.
这是单写单读
的:
如果你知道如何安全
地访问变量
,则可用shared
.我坚持:永远不要使用__gshared
.
快速测试表明extern(C) extern shared
工作很好.
据我所知,__gshared
仅在,你想在单线程
程序中访问共享C变量
时才工作良好.然后,如果稍后用多线程
,你仍然会失败
.
所以,永远不要(在多线程
代码中)使用__gshared
.
C没有共享
概念,所以不是正确类型
.加上shared
只是假
,并会导致麻烦.最好明确
说明.
并不是说你应该自由使用__gshared
,或只在D中
使用.而是说永远不应
使用它,这是错误的.
废话.在共享变量上加shared
不是"说谎".C
是否区分并不重要.但D
重要.
如果你可识别出__gshared
的有效用例
,并用它编写
正确代码,则你就知道什么
时候不听我的.
其他人,永远
不要使用__gshared
.
__gshared
和-boundscheck=off
一样糟糕.它们都是明显的安全漏洞
.
你的问题在此,而不是因为它是__gshared
.
你复制了该值,显然可同时更改它,这是常识.
你不应这样使用它.而应该直接访问s.x
.
而用共享
,如果读取线程
时先锁定,则结果相同,且在更改前
会读取并处理该值.
读x
时,就改了x
.
shared
并不能解决条件竞争,这是对的.如果没有-preview=nosharedaccess
,则无区别.所以不妨使用shared
😉.
但是有了-preview=nosharedaccess
,代码不再编译,你不得不
考虑如何安全
访问共享数据
.哪个好?
所以:永远不要使用__gshared
,总是用-preview=nosharedaccess
.
如果你有更好
抽象且仔细锁定
访问数据,但C不行
,如果想访问C全局变量
,应使用__gshared
,因为这就是它的用途
.使用shared
,帮不了你.
使用__gshared
来共享数据给C
,与使用-boundscheck=on
发送数组到无此类限制的C中
一样安全.
这里结论
真的应该是,不要使用C
.
不,使用shared
确实可以帮你.
C没有shared
限定符,但C程序员
仍然必须考虑线程安全
.调用C函数
或访问C全局变量
必须考虑多线程
.shared加上(-preview=nosharedaccess)
迫使你考虑合同
是什么.__gshared
没有.
不,这不对.C
总是不安全
的,这是正确的,但不重要.关键是你在D端
可以/不能做什么
.
-boundscheck=on
,不会轻易在D端
搞砸.C
端还是可以乱七八糟的.
-boundscheck=off
,很容易
在D端搞砸.
shared
,不会轻易在D端搞砸.C
端还是可以乱七八糟的.
__gshared
,很容易在D端
搞砸.
shared
让你感觉该语言
帮你预防问题.同样,对C,这是假的
.
边界
在C和D中的定义相同,有指针
和大小
,你不能超过那个大小.是的,数据以不同的方式传达,但这很容易理解和使用.
shared
(加上-preview=nosharedaccess
),阻止
你上场.不会犯规.不能伤害自己
.可通过强制转换
告诉编译器(1)
你确定要玩,及(2)
,你将按C端的规则玩.
__gshared
只是让你在球场
上奔跑.不知道规矩?编译器不在乎.玩得开心
打断你的腿.
用__gshared
:
我甚至
未发现我在做危险
事情,因为第一次天真
的通过了编译且似乎工作正常
.
使用shared
(加-preview=nosharedaccess
):
如果查看文档,会发现关于正确用法
.正如你所建议的,我想出了:
我被迫更多
地考虑线程安全
.这里可以丢弃shared
,因为调用了线程安全的properlyUse
函数.所以:
用__gshared
这不大会发生.没有转换
的调用properlyUse
可能更好,但我不信人们记得
在没有编译器
对他们大喊大叫
时就使用该函数.
即使他们第一次做对了,随着时间
推移,他们也一定会失败.当简单的,错误的
代码编译时,它肯定会进入源文件
.
很难做到正确的线程安全
.需要从编译器
中获得的所有帮助.__gshared
提供零帮助.shared
至少高亮
了有趣的地方.