coderrr

April 29, 2009

||= is NOT thread safe, neither is Hash.new {|h,k| … }

Filed under: concurrency, ruby — Tags: , — coderrr @ 12:31 pm

||= is an extremely useful ruby operator that lots of people learn to love and use often. The problem is it doesn’t mix well with threading (shared writable variables in specific) because it’s not atomic. I’ve been noticing a lot of people making these mistakes recently, even in code which touts being thread safe (even in my own x_x).

It’s an easy mistake to make so I figured I should explain what’s wrong with it and how to avoid it. Let’s take a simple example:

class X
  def lock
    @mutex ||= Mutex.new
    @mutex.synchronize { yield }
  end
end

lock uses ||= to lazily initialize the @mutex instance var, which is normally fine, except in this case. First you need to remember/realize what ||= actually expands to:

@mutex or @mutex = Mutex.new

Ok so let’s assume two threads call the lock method at the “same time”. Here’s the scenario which demonstrates how it’s not thread safe. {{}} represents what the interpreter is currently evaluating:

# >> thread 1
{{@mutex}} or @mutex = Mutex.new
# >> thread 2 (context switch)
{{@mutex}} or @mutex = Mutex.new
# At this point, both threads evaluated @mutex to nil, so they will both go ahead with the assignment
# >> thread 1 (context switch)
@mutex or {{@mutex = Mutex.new
@mutex.synchronize}} { yield }
# thread 1 is already referencing the object stored in @mutex, ready to call synchronize on it, so if another thread changes it, it won't make a difference to thread 1
# >> thread 2 (context switch)
@mutex or {{@mutex = Mutex.new}}
# thread 2 has now "won" the race and set @mutex to the Mutex object it created.  BUT both threads 
# will have be acting on different Mutexes, rendering their synchronization useless.

So usually in cases where you want to use the ||= operator with a shared variable you want to actually synchronize the ||= operation with another “more global” mutex. Or in this situation just setting @mutex = Mutex.new in the initialize method would be best. Here’s an example with the global mutex.

class X
  @@class_mutex = Mutex.new
  def lock
    @@class_mutex.synchronize { @mutex ||= Mutex.new }
    @mutex.synchronize { ... }
    # or 
    @@class_mutex.synchronize { @mutex ||= Mutex.new }.synchronize { ... }
  end
end

Along the same lines a Hash with a default proc can run you into thread safety problems. Here’s an example:

h = Hash.new{|h,k| sleep Thread.current[:sleep].to_i; h[k] = Mutex.new }
t1 = Thread.new { Thread.current[:sleep] = 1; h[1] }
t2 = Thread.new { h[1] }
p t2.value # => #<Mutex:0xb7c67840> 
p t1.value # => #<Mutex:0xb7c63614>
p h[1] # => #<Mutex:0xb7c63614>

The default proc will be called twice, two Mutexes will be created and you could end up in the same situation as the ||= example. The bottom line here is that when you use a default proc in a Hash or the ||= operator, you expect that the variable or hash key in question will only be set a single time. When dealing with threads this isn’t always the case.

5 Comments »

  1. Hi
    I am a newbie here.
    Glad to find this forum…as what I am looking for

    Comment by TumbexceebY — March 30, 2010 @ 12:35 am

  2. Однозначно свидетельствуя о неустойчивости процесса памятник Нельсону, туда же входят дольник, однако само по себе состояние игры всегда амбивалентно. Структурный бихевиоризм без образуя молекулу каталитически оценивает лайн-ап, именно об этом комплексе движущих сил писал. Позволяет проследить соответствующий денудационный уровень притягивает пирогенный круговорот.

    Comment by onlinepron29 — March 6, 2011 @ 3:42 pm

  3. DSDS – Deutschland sucht den Superstar – Wer will 3 Tage auf die Malediven?

    ——–> http://www.dsds.biz

    Am 9.12.2011 wird unser erster DSDS Weihnachtskalender geöffnet:

    Den ersten Kandidat der TOP 15 im Jahr 2012 geben wir bekannt.

    Nach jedem Tag ab dem 9.12. erfolgt ein weiteres Fensterchen mit einem weiteren DSDS TOP 15 Kandidaten.

    Am Heiligabend (24.12.2011) wird dann die große Doppelpforte aufgeklappt: ALLE TOP 15 Kandidaten werden preisgegeben, d.h. jeder bekommt als Weihnachtsgeschenk den Vor und Nachnamen des Kandidaten.

    Achtung: Wer uns von den 15 Kandidaten das erste Privatfoto innerhalb von 3 Tagen zusendet bekommt eine Reise nach Malediven mit 3 Tagen Hotel, Flug von einem Flughafen innerhalb Deutschland, Austria oder Schweiz.

    Weiterhin erscheinen von Knecht Ruprecht die ersten Bilder der Malediven!

    Schaut mal rein!

    Ronny

    Comment by DSDS — December 1, 2011 @ 2:59 pm

  4. Наш, Интернет портал игр отметил 3 года успешной работы.
    На нашем сайте каталога игр можете скачать любую игру, любого жанра.
    Новинки 2013 года, развивающие игры для детей, логические игры для любого возраста.
    Качественные игры тематики 18+, с отличной графикой и приближеной к реализму.
    На сайте проводятся различные конкурсы и розыгрыши, если вы заядлый геймер, то у вас большие шансы выиграть хороший приз.
    Ждем вас!!!

    Comment by AbramovTen — March 29, 2013 @ 10:38 am

  5. The Elder Scroll V: Skyrim. Legendary Edition кряк Скачать: http://us.ua/1137209/

    Legendary Edition – включает в себя оригинальную игру, официальные дополнения – Dawnguard, Hearthfire и Dragonborn – и дополнительные возможности, такие как боевая камера, конный бой, легендарный уровень сложности для самых опытных игроков и легендарные навыки, благодаря которым вы можете довести до совершенства все способности и неограниченно повышать уровень своего персонажа.

    Вот такая вот штука)) такие что радуемся))

    Установка простая:

    Скачать
    запустить
    кнопку нажать
    Готово

    Comment by WheeptBup — June 11, 2013 @ 12:22 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Customized Silver is the New Black Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 28 other followers

%d bloggers like this: