Organized Thread Collisions

We don’t like when things collide.

Absolutely no head on collisions

Photo by szlea

But what if we need them to? What if we want to ensure that should a collision between threads happen, things will not go out of hand?

This is remarkably easy to do. Let’s pretend we want $somevar to be thread-safe:

require 'test/unit'

class Collision < Test::Unit::TestCase
  def test_that_fails
    a = Thread.new do
      5.times do | t |
        $somevar = true
        sleep(rand(10)/200.0)
        assert_equal true, $somevar,
		  "Somevar should keep the state true"
      end
    end
  
    b = Thread.new do
      5.times do | t |
        $somevar = false
        sleep(rand(10)/200.0)
        assert_equal false, $somevar, 
          "Somevar should keep the state false"
      end
    end
    
    ensure
     a.join; b.join 
  end
end

Fail. Global variables are never thread-safe, neither are class variables and module attributes.

The .times call is somewhat cargo cult programming, because this fails for me on first iteration. Replace the $somevar with your getter and setter and you should see negative results immediately.

How does it work? Simple - we are spinning off two threads, they set the variable and wait in Kernel#sleep for the other thread to arrive and do it’s own assignment. It ensures that between the variable assignment and the assertion there’s just enough time for another thread to set the new value for the variable.