ruby-concurrency/thread_safe

ThreadSafe::Cache#fetch_or_store thread safety

etehtsea opened this issue · 2 comments

require 'monitor'
require 'thread_safe'

class AppConfig
  LOCK = Monitor.new

  class << self
    def object
      instance.fetch_or_store(:object) { Object.new }
    end

    private

    def instance
      @instance || LOCK.synchronize { @instance ||= ThreadSafe::Cache.new }
    end
  end
end

threads = 100.times.map do
  Thread.new { AppConfig.object }
end

p threads.map(&:value).map(&:object_id).uniq
⚡ rbenv shell jruby-1.7.15
⚡ ruby safety.rb
[2000, 2002, 2004, 2006, 2008, 2010, 2012]

Is this expected behaviour?

@etehtsea sorry for taking so long to reply, I wasn't github-watching this repository.

As to your question: yes, fetch_or_store does not guarantee atomicity, see also headius/thread_safe#45.

I'm sorry for the complete absence of any docs, for TS::Cache only these methods are atomic: put_if_absent, compute_if_absent, compute_if_present, compute, merge_pair, replace_pair, replace_if_exists, get_and_set, delete, delete_pair.

Thanks for your answer!