rails/rails — pull request #8510 by thedarkone (2012-12-13 14:12:31+00:00)
Title: Thread safety improvements

**I don't expect this to be insta-merged - discussion, code review and suggestions are welcome.**

The problem is that there are heaps of non thread safe usage of Hashes in Rails and the surrounding gems. This needs to be fixed. Instead of littering the whole code base with the `synchronize {}` blocks, it is better done by creating a fully thread-safe hash-like data structure.

This is where `ThreadSafe::Cache` comes in. It is:
* a thread-safe hash-like data structure
* reads are lock-free
* writes might be using locks, but this is fixable in the future
* storing an item in `Cache` constitutes safe publication
* reads have volatile semantics (allows for properly done double-checked locking idiom)
* writes have volatile semantics

Implementation details are as follows:
* on MRI 1.8/1.9/2.0 it is a [thin wrapper](https://github.com/headius/thread_safe/blob/master/lib/thread_safe/non_concurrent_cache_backend.rb) around a `Hash` class that [mostly](https://github.com/headius/thread_safe/blob/master/lib/thread_safe/mri_cache_backend.rb) relies on GIL for protection
* on JRuby it uses native [Java `ConcurrentHashMap`](https://github.com/headius/thread_safe/blob/master/ext/org/jruby/ext/thread_safe/JRubyCacheBackendLibrary.java)
* on Rubinius it uses a [pure Ruby](https://github.com/headius/thread_safe/blob/master/lib/thread_safe/atomic_reference_cache_backend.rb) port of Doug Lea's new JDK8 `java.util.concurrent.ConcurrentHashMap`
* everywhere else it defaults to a [fully synchronized](https://github.com/headius/thread_safe/blob/master/lib/thread_safe/synchronized_cache_backend.rb) `Hash` wrapper

Why is it better than explicit synchronisation?

A thread-safe hash is a very useful abstraction, it simplifies the code and allows to avoid worrying about thread-safety most of the time. Explicit locking is not so easily done and is prone to missing some code paths. As the amount of explicit locks increases, so does the probability of deadlocks. Locks are slightly slower than lock-free volatile reads and scale horribly as the concurrency level increases.