【发布时间】:2019-08-26 15:38:20
【问题描述】:
我今天遇到了这段代码:
@thread ||= Thread.new do
# this thread should only spin up once
end
它被多个线程调用。我担心如果多个线程正在调用此代码,您可能会创建多个线程,因为@thread 访问不同步。但是,有人告诉我,由于 Global Interpreter Lock,这不可能发生。我对 Ruby 中的线程做了一些阅读,似乎运行 Ruby 代码的单个线程可能会被其他线程抢占。如果是这样的话,你不能有这样的交错:
Thread A Thread B
======== ========
Read from @thread .
Thread.New .
[Thread A preempted] .
. Read from @thread
. Thread.New
. Write to @thread
Write to @thread
此外,由于对@thread 的访问不同步,是否保证对所有其他线程可见对@thread 的写入?我过去使用的其他语言的内存模型不能保证写入内存的可见性,除非您使用原子、互斥锁等同步对该内存的访问。
我仍在学习 Ruby,并意识到要理解 Ruby 中的并发性还有很长的路要走。对此的任何帮助将不胜感激!
【问题讨论】:
-
||=不是线程安全的,除非您使用 Mutex 来锁定它。这不是原子操作,而是三个操作(读取、测试、设置),其中有很多线程问题的空间。 -
@tadman 这是我的怀疑。我正在做一个实验来尝试展示这种交错。但是,我不知道如何鼓励线程调度程序以高速率抢占。
-
如果您需要这样做,请使用
Mutex#synchronize。
标签: ruby multithreading concurrency thread-safety