3

I need some help in understanding Hash in Ruby 1.8.7.

I have a multi-threaded Ruby application, and about 95% of time multiple threads of the application are trying to access a global Hash.

I am not sure if the default Ruby Hash is thread safe. What would be the best way to have a fast Hash but also one that is thread safe given my situation?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Fanatic23
  • 3,378
  • 2
  • 28
  • 51
  • What operations are being performed on this hash? Typically you want to use a mutex to manipulate thread-shared resources. – coreyward Feb 13 '12 at 18:48
  • Are you trying to read, or change the hash? Reads are safe. – the Tin Man Feb 13 '12 at 18:48
  • @theTinMan: I have couple of threads reading from the hash frequently . Writing to the hash happens at a far slower rate. I need to ensure that while trying to synchronize the writes I don't end up slowing the reads. – Fanatic23 Feb 14 '12 at 04:35
  • I think you'd be safe with a [mutex](http://ruby-doc.org/core-1.9.2/Mutex.html) also. Slowing the reads shouldn't be an issue since the write/update would occur very fast. Writing a [benchmark](http://ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html) would prove/disprove that. – the Tin Man Feb 14 '12 at 17:17
  • @Fanatic23, are you interested in seeing an implementation of a read-write lock? If you're not familiar with the term, it is like a mutex, but it allows any number of readers to run concurrently, but only 1 writer (and once a writer gets the lock, all the readers have to wait). – Alex D Feb 15 '12 at 18:19
  • @AlexD: Sure, and +1 for the answer. Thanks for the help. – Fanatic23 Feb 15 '12 at 18:58
  • I have put my read-write lock implementation up on StackExchange Code Review to get suggestions for improvement. Readers of this thread, please offer any suggestions you can! http://codereview.stackexchange.com/questions/9038/read-write-lock-implementation-for-ruby – Alex D Feb 16 '12 at 11:12
  • @Fanatic23, me and 2 other people have tested ReadWriteLock on several Ruby implementations, and I (tentatively) think it may be ready for you to use. Have a look and tell me what you think! – Alex D Feb 23 '12 at 14:12

2 Answers2

2

The default Ruby Hash is not thread-safe. On MRI and YARV it is "somewhat accidentally thread-safe", because MRI and YARV have a broken threading implementation that is incapable of running two threads simultaneously anyway. On JRuby, IronRuby and Rubinius however, this is not the case.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
1

I would suggest a wrapper which protects the Hash with a read-write lock. I couldn't find a pre-built Ruby read-write lock implementation (of course JRuby users can use java.util.concurrent.ReentrantReadWriteLock), so I built one. You can see it at:

https://github.com/alexdowad/showcase/blob/master/ruby-threads/read_write_lock.rb

Me and two other people have tested it on MRI 1.9.2, MRI 1.9.3, and JRuby. It seems to be working correctly (though I still want to do more thorough testing). It has a built-in test script; if you have a multi-core machine, please download, try running it, and let me know the results! As far as performance goes, it trounces Mutex in situations with a read bias. Even in situations with 80-90% writes, it still seems a bit faster than using a Mutex.

I am also planning to do a Ruby port of Java's ConcurrentHashMap.

Alex D
  • 29,755
  • 7
  • 80
  • 126
  • Please note that you must first install the excellent "atomic" gem, from Charles Nutter and MeNTaLGuY! – Alex D Feb 23 '12 at 14:15
  • @Alex_D I have a similar question to your answer here. Mainly, I'd rather not use your code, but would rather just use the Atomic library, if indeed that is sufficient. Can you take a look: [Using Threadsafe Initialization in a JRuby Gem](http://stackoverflow.com/questions/19104886/using-threadsafe-initialization-in-a-jruby-gem) – likethesky Oct 22 '13 at 21:44