Last active
December 19, 2020 16:24
-
-
Save romuloceccon/f44a30cb43f8081279a484193d386f55 to your computer and use it in GitHub Desktop.
Demonstrates how Ruby's idiom "my_var ||= MyObject.new" is NOT thread safe, as part of discussion at https://github.com/svenfuchs/i18n/pull/352#pullrequestreview-24816351. The script returns when a race condition is detected.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyObject | |
def initialize | |
@data = 'x' * 1_000_000 | |
end | |
def inspect | |
object_id | |
end | |
end | |
# Unsafe function being tested | |
def init_once | |
$init_once_var ||= MyObject.new | |
end | |
loop do | |
$init_once_var = nil | |
$new_objects = [] | |
$lock = Mutex.new | |
threads = (1..10).map do | |
Thread.new do | |
obj = init_once | |
$lock.synchronize do | |
$new_objects << obj unless $new_objects.include?(obj) | |
end | |
end | |
end.each { |t| t.join } | |
if $new_objects.length != 1 | |
puts $new_objects.inspect | |
break | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment