Created
April 15, 2015 22:01
-
-
Save film42/e3f0c8442fe7ea686cb7 to your computer and use it in GitHub Desktop.
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
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