Skip to content

Instantly share code, notes, and snippets.

@billdueber
Last active August 29, 2015 14:02
Show Gist options
  • Save billdueber/7c9a37ce2c2f09e97b64 to your computer and use it in GitHub Desktop.
Save billdueber/7c9a37ce2c2f09e97b64 to your computer and use it in GitHub Desktop.
Demonstration of MRI thread pools failing to do all their work
require 'concurrent'
require 'thread'
# A simple safe array implementation.
class SafeArray
def initialize
@write_mutex = Mutex.new
@arr = []
end
def <<(x)
@write_mutex.synchronize do
@arr << "#{x}"
end
end
def size
@write_mutex.synchronize do
@arr.size
end
end
end
# Get a pool with three threads and a safe array
pool = Concurrent::FixedThreadPool.new(3, :overflow_policy => :caller_runs)
sa = SafeArray.new
sa << "Starting..."
# Stick the numbers 0..4 in the safe array
5.times do |x|
pool.post do
sa << x
end
end
# If you pass a numeric argument, we sleep that long
# to show that a forced pause allows the threads time
# to terminate normally, but the combination of #shutdown
# and #wait_for_termination doesn't
unless ARGV[0].nil?
wait_seconds = ARGV[0].to_f
sleep wait_seconds
end
# Do an orderly shutdown
pool.shutdown
pool.wait_for_termination(500)
puts "Total size is #{sa.size}"
# Run this in sets of three, once without a delay and once with a 0.25-second delay
#
# > ruby -v
# ruby 2.1.0dev (2013-11-23 trunk 43807) [x86_64-darwin11.0]
# > for i in 1 2 3; do ruby thread_pool_failure.rb; done
# Total size is 1
# Total size is 1
# Total size is 1
#
# Oops! Looks like the threads aren't getting their data into the safe array -- just the "Starting..." string.
# Suppose we force a quarter-second delay before calling #shutdown?
#
# > for i in 1 2 3; do ruby thread_pool_failure.rb 0.25; done
# Total size is 6
# Total size is 6
# Total size is 6
# JRuby doesn't exhibit this behavior; it gets it right every time
# > ruby -v
# jruby 1.7.10 (1.9.3p392) 2014-01-09 c4ecd6b on Java HotSpot(TM) 64-Bit Server VM 1.8.0-b132 +indy [darwin-x86_64]
# > for i in 1 2 3; do ruby thread_pool_failure.rb; done
# Total size is 6
# Total size is 6
# Total size is 6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment