Skip to content

Instantly share code, notes, and snippets.

@film42
Created April 15, 2015 22:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save film42/e3f0c8442fe7ea686cb7 to your computer and use it in GitHub Desktop.
Save film42/e3f0c8442fe7ea686cb7 to your computer and use it in GitHub Desktop.
require 'thread'
##
## THREADING EXAMPLE
##
## Ruby's array append is not "thread safe." This means that real
## concurrency models will have collision issues. This is not a good
## thing, but we'll find we can use real threading constructs to
## protect code that isn't "thread safe." Run this code on MRI and
## then try running this in jRuby and compare the results.
# Let's run 5 threads, and each of them will append `array' with nil a
# thousand times. We will wait for the threads to finish using
# `.join', and then we will print the array size. You'd think this
# should be 5000, but this code isn't thread safe, so this will
# actually not give you the results you expect on a platform that
# supports real concurrency.
array = []
puts "Running non-thread-safe code"
5.times.map do
Thread.new do
1000.times do
array << nil
end
end
end.each(&:join)
puts array.size
# This will not work on java, since we don't need to fork a process.
# Forking a process means we're going to start a new program with new
# memory. So, you'll find that when we run this under MRI, the size of
# the array is going to be 0, because each process will change `array'
# but those changes won't be visible to the main application.
if RUBY_PLATFORM != "java"
array = []
puts "Running with fork:"
5.times.map do
Thread.new do
fork do
1000.times do
array << nil
end
end
end
end.each(&:join)
puts array.size
end
# We will now introduce the concept of a mutex (mutual exclusion). The
# actual name for the code that's giving us mutual exclusion is called
# a semaphore (like spanish for intersection, I think). We will use
# this to synchronize the appending to array. Even though array append
# is not thread safe, we can let one thread touch array at a time with
# the mutex, and this will give us guarentees that our array will be
# of size 5000.
semaphore = Mutex.new
array = []
puts "Running with a Mutex:"
5.times.map do
Thread.new do
1000.times do
semaphore.synchronize do
array << nil
end
end
end
end.each(&:join)
puts array.size
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment