Skip to content

Instantly share code, notes, and snippets.

@mikbe
Created June 17, 2011 13:30
Show Gist options
  • Select an option

  • Save mikbe/1031419 to your computer and use it in GitHub Desktop.

Select an option

Save mikbe/1031419 to your computer and use it in GitHub Desktop.
Stops collisions but it's ugly
require 'thread'
module ThreadSafe
def self.included(base)
base.extend(ThreadSafeClassMethods)
base.threadsafe_class_mutex = Mutex.new # <= This should be threadsafe by its very nature
end
module ThreadSafeClassMethods
attr_accessor :threadsafe_class_mutex
end
def threadsafe_mutex
self.class.threadsafe_class_mutex.synchronize {
@mutex ||= Mutex.new
}
end
end
class Foo
include ThreadSafe
attr_accessor :bar
def baz
threadsafe_mutex.synchronize {
@bar ||= rand(10000000000)
}
end
end
f = Foo.new
f2 = Foo.new
baz1 = -1
baz2 = -1
count = 0
last_one = ""
show_once = true
while baz1 == baz2
last_one = "f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}"
f.bar = nil
wait_til = Time.now + 0.01
Thread.new {sleep (wait_til - Time.now); baz1 = f.baz }
Thread.new {sleep (wait_til - Time.now); baz2 = f.baz }
sleep 0.02
count += 1
if count == 100
puts "working: #{last_one}"
count = 0
end
if show_once
show_once = false
# only want to run these after the classes have had a chance to instnatiate the mutexes,
# not force them to be instantiated (thus negating the reason for the test)
puts "Class mutex: #{f.class.threadsafe_class_mutex}"
puts "instance mutex: #{f.threadsafe_mutex}"
puts "instance mutex: #{f2.threadsafe_mutex}" # Just to verify instances are getting their own mutexes
end
end
puts
puts "Thread collision"
puts "previous: #{last_one}" # Just to prove it's not remembering value from last iteration but is a real collision
puts "current: f.bar: #{f.bar}; baz1: #{baz1}; baz2: #{baz2}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment