Module: Concurrent::Synchronization

Defined in:
lib/concurrent/synchronization.rb,
lib/concurrent/synchronization/lock.rb,
lib/concurrent/synchronization/object.rb,
lib/concurrent/synchronization/volatile.rb,
lib/concurrent/synchronization/condition.rb,
lib/concurrent/synchronization/mri_object.rb,
lib/concurrent/synchronization/rbx_object.rb,
lib/concurrent/synchronization/jruby_object.rb,
lib/concurrent/synchronization/truffle_object.rb,
lib/concurrent/synchronization/lockable_object.rb,
lib/concurrent/synchronization/abstract_struct.rb,
lib/concurrent/synchronization/abstract_object.rb,
lib/concurrent/synchronization/rbx_lockable_object.rb,
lib/concurrent/synchronization/mri_lockable_object.rb,
lib/concurrent/synchronization/jruby_lockable_object.rb,
lib/concurrent/synchronization/truffle_lockable_object.rb,
lib/concurrent/synchronization/abstract_lockable_object.rb

Overview

Synchronization

This document is moved to Google documents. It will be moved here once final and stabilized.

Concurrent Ruby Notes

Locks

Concurrent Ruby also has an internal extension of Object called LockableObject, which provides same synchronization primitives as Java's Object: synchronize(&block), wait(timeout = nil), wait_until(timeout = nil, &condition), signal, broadcast. This class is intended for internal use in concurrent-ruby only and it does not support subclassing (since it cannot protect its lock from its children, for more details see this article). It has minimal interface to be able to use directly locking available on given platforms.

For non-internal use there is Lock and Condition implementation in Synchronization namespace, a condition can be obtained with new_condition method on Lock. So far their implementation is naive and requires more work. API is not expected to change.

Method names conventions

Methods starting with ns_ are marking methods that are not using synchronization by themselves, they have to be used inside synchronize block. They are usually used in pairs to separate the synchronization from behavior and to allow to call methods in the same object without double locking.

class Node
  # ...
  def left
    synchronize { ns_left }
  end  

  def right
    synchronize { ns_right }
  end  

  def to_a
    # avoids double locking
    synchronize { [ns_left, ns_right] }
  end    

  private

  def ns_left
    @left
  end

  def ns_right
    @right
  end
  # ...
end

Piggybacking

Any write executed before volatile write based on program-order is visible to the volatile read as well, which allows piggybacking. Because it creates synchronizes-with (JMM term) order between volatile write and read, which participates in creating happens-before order.

This trick is used in some of the abstractions, to avoid unnecessary synchronization or volatile declarations.

Defined Under Namespace

Modules: JRubyAttrVolatile, MriAttrVolatile, RbxAttrVolatile, TruffleAttrVolatile Classes: Condition, Lock, Object, TruffleLockableObject

Constant Summary

Volatile =

Volatile adds the attr_volatile class method when included.

foo = Foo.new foo.bar => 1 foo.bar = 2 => 2

Examples:

class Foo
  include Concurrent::Synchronization::Volatile

  attr_volatile :bar

  def initialize
    self.bar = 1
  end
end
case
when Concurrent.on_cruby?
  MriAttrVolatile
when Concurrent.on_jruby?
  JRubyAttrVolatile
when Concurrent.on_rbx? || Concurrent.on_truffle?
  RbxAttrVolatile
else
  MriAttrVolatile
end