ruby - 用 Ruby 解释这种竞争条件
问题描述
四个线程每个循环 1000 万次。在每个循环中,如果列表为空,他们会推送一个数字,否则他们会从列表中弹出一个数字。
list = []
threads = []
4.times do |i|
threads << Thread.new do
1e7.to_i.times do |i|
if list.empty?
list << i
else
list.pop
end
end
end
end
threads.each(&:join)
p list
由于循环执行偶数次,我希望在所有线程执行后列表为空。
但是,有时列表中包含数字 9999999。
由于 GIL,我认为 MRI Ruby 中的 Array 是线程安全的。
尽管有 GIL,竞争条件是如何发生的?
解决方案
当时只执行一个线程并不意味着一个线程总是在有用的行停止,例如在下一个线程获得其执行时间之前在块的末尾。
在您的示例中,一个线程可能会读取和评估list.empty?
,然后必须等待另一个线程。另一个线程也读取和评估list.empty?
并获得与第一个线程相同的结果。之后,两个线程将执行相同的if
条件分支,因为它们看到了相同的状态。
推荐阅读
- python - How do I call a function within my class?
- python - 从python中列表列表的标记中展平列表?
- jquery - How to change jQuery terminal --char-width
- html - 如何删除导航栏下不需要的 1px 空间?
- javascript - Webpack 在单个进程/相同端口上具有节点后端,前后热重载......?
- android - 我如何在 CoroutineScope 内取消并检测取消
- azure - Azure AD Graph API 或 Microsoft Graph API 中的更新是如何发布的
- java - 可以在使用 openCSV 导出数据时删除分隔符吗?
- android - 像“绿色”这样的颜色是在 Color.parseColor() 中硬编码的,还是使用 R.color 中的值?
- sql - 在 ORACLE 中使用 2 个条件计数