同时运行两个线程在同时写入和读取两个线程的变量时会产生奇怪的行为。它可以是线程安全的,但不是在所有情况下。
线程安全示例:TThread.Terminated
布尔终止只读FTerminated,它只设置一次,因为它是布尔值,所以写入过程是原子的。因此,可以在MainThread和线程中读取该值,并且始终可以读取线程安全。
我的例子:我有一个字符串,只写一次。与TThread.Terminated不同,我的字符串的写入不是原子的,因此读取它本身并不是线程安全的。但是在特殊情况下可能存在线程安全的方式:我有一种情况,我只想将字符串与另一个字符串进行比较。如果它们是相同的,我只会做一些事情(如果它们不相等则并不重要,因为字符串尚未完全写入)。所以我想到这是否可以是线程安全的。那么当字符串被写入时会发生什么呢?如果我只读了一半就读了字符串会出错?
编写字符串时要执行的步骤:
在什么情况下读取在同一时刻写入的字符串是否安全?
对那些具有如此深刻知识的人提出质疑:我的假设是真的吗?如果是的话,我可以安全地依赖它吗?或者依靠这个实现细节是一个如此糟糕的想法,它甚至不值得考虑所有这些并且只是在它们被写入另一个线程时不会无保护地读取字符串?
答案 0 :(得分:3)
Delphi字符串是“线程安全的”,只是在某种意义上,字符串的引用计数在多线程代码中保证有效。
Delphi字符串的Copy-On-Write是不线程安全操作;如果您需要对同一个字符串进行多线程读/写访问,通常应该使用一些同步,否则您可能会遇到麻烦。
答案 1 :(得分:0)
在没有任何锁的情况下可能发生的情况的示例。
正在写入字符串:它应该变得比以前更大,因此将分配新的内存。但是指针尚未修改,它指向旧字符串。
同时,读取线程获得了一个指针,并开始读取旧字符串。
上下文再次切换到写入线程。它更改了指针,因此现在有效。旧字符串的引用计数为0,并立即被释放。
再次进行上下文切换:读取线程继续处理旧字符串,但是现在可以访问释放的内存,这很容易导致访问冲突。