diff --git a/README b/README
deleted file mode 100644
index 7ef00b47866b5d73efb30167e59ccecd632372b2..0000000000000000000000000000000000000000
--- a/README
+++ /dev/null
@@ -1,16 +0,0 @@
-avl_tree - AVL tree and Red-black tree in Ruby
-Copyright (C) 2012 Hiroshi Nakamura <nahi@ruby-lang.org>
-
-
-== Author
-
-Name:: Hiroshi Nakamura
-E-mail:: nahi@ruby-lang.org
-Project web site:: http://github.com/nahi/avl_tree
-
-
-== License
-
-This program is copyrighted free software by Hiroshi Nakamura.  You can
-redistribute it and/or modify it under the same terms of Ruby's license;
-either the dual license version in 2003, or any later version.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..449836a56e6addd4f85653c8a73f6cd73b64d3b8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,42 @@
+# AVL tree, Red-black tree in Ruby
+
+avl_tree - AVL tree, Red-black tree and Lock-free Red black tree in Ruby
+Copyright (C) 2014 Hiroshi Nakamura <nahi@ruby-lang.org>
+
+
+## Usage
+
+You can use AVLTree, RedBlackTree or ConcurrentRedBlackTree just as a
+replacement of Hash.
+
+    @points = Hash.new
+    ...
+    @points[score] = person
+    ...
+    @points.each do |score, person|
+      ...
+    end
+
+    ->
+
+    require 'avl_tree'
+    @points = AVLTree.new
+
+    require 'red_black_tree'
+    @points = RedBlackTree.new
+    @points = ConcurrentRedBlackTree.new
+
+AVLTree and RedBlackTree are faster but not thread-safe.  Use ConcurrentRedBlackTree in multi-thread environment.
+
+## Author
+
+Name:: Hiroshi Nakamura
+E-mail:: nahi@ruby-lang.org
+Project web site:: http://github.com/nahi/avl_tree
+
+
+## License
+
+This program is copyrighted free software by Hiroshi Nakamura.  You can
+redistribute it and/or modify it under the same terms of Ruby's license;
+either the dual license version in 2003, or any later version.
diff --git a/avl_tree.gemspec b/avl_tree.gemspec
new file mode 100644
index 0000000000000000000000000000000000000000..09394ad5e852ef0fcee3b5bac88b43ff065a2285
--- /dev/null
+++ b/avl_tree.gemspec
@@ -0,0 +1,32 @@
+#########################################################
+# This file has been automatically generated by gem2tgz #
+#########################################################
+# -*- encoding: utf-8 -*-
+# stub: avl_tree 1.2.1 ruby lib
+
+Gem::Specification.new do |s|
+  s.name = "avl_tree".freeze
+  s.version = "1.2.1"
+
+  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+  s.require_paths = ["lib".freeze]
+  s.authors = ["Hiroshi Nakamura".freeze]
+  s.date = "2014-09-28"
+  s.email = "nahi@ruby-lang.org".freeze
+  s.files = ["README.md".freeze, "bench/bench.rb".freeze, "bench/bench_element_size.rb".freeze, "bench/bench_thread.rb".freeze, "bench/profile.rb".freeze, "lib/avl_tree.rb".freeze, "lib/red_black_tree.rb".freeze, "test/helper.rb".freeze, "test/test_avl_tree.rb".freeze, "test/test_red_black_tree.rb".freeze, "test/test_red_black_tree_thread.rb".freeze]
+  s.homepage = "http://github.com/nahi/avl_tree".freeze
+  s.rubygems_version = "2.5.2.1".freeze
+  s.summary = "AVL tree, Red black tree and Lock-free Red black tree in Ruby".freeze
+
+  if s.respond_to? :specification_version then
+    s.specification_version = 4
+
+    if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
+      s.add_runtime_dependency(%q<atomic>.freeze, ["~> 1.1"])
+    else
+      s.add_dependency(%q<atomic>.freeze, ["~> 1.1"])
+    end
+  else
+    s.add_dependency(%q<atomic>.freeze, ["~> 1.1"])
+  end
+end
diff --git a/bench/bench_thread.rb b/bench/bench_thread.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c469774449f420b3e986f6ec703b7700ab37665b
--- /dev/null
+++ b/bench/bench_thread.rb
@@ -0,0 +1,39 @@
+require 'benchmark'
+require 'red_black_tree'
+
+Benchmark.bmbm do |bm|
+  bm.report do
+    h = ConcurrentRedBlackTree.new
+    num = 100000
+    max = 1000
+    threads = []
+    # writers
+    2.times do
+      threads << Thread.new {
+        num.times do
+        key = rand(max)
+        h[key] = key
+        end
+      }
+    end
+    # deleters
+    2.times do
+      threads << Thread.new {
+        num.times do
+        key = rand(max)
+        h.delete(key)
+        end
+      }
+    end
+    # readers
+    2.times do
+      threads << Thread.new {
+        num.times do
+        key = rand(max)
+        h[key]
+        end
+      }
+    end
+    threads.each(&:join)
+  end
+end
diff --git a/lib/avl_tree.rb b/lib/avl_tree.rb
index c9b8af3ff648b8c5b0f4261a0c8a245aa374c265..abd63fc35ac1d51b6889dc4f952cbf1695ea61f6 100644
--- a/lib/avl_tree.rb
+++ b/lib/avl_tree.rb
@@ -314,6 +314,10 @@ class AVLTree
   end
   alias length size
 
+  def height
+    @root.height
+  end
+
   def each(&block)
     if block_given?
       @root.each(&block)
diff --git a/lib/red_black_tree.rb b/lib/red_black_tree.rb
index ee5e0cea72baa05806279f6858499eb38a9bf56d..c69435f9a59fce9442e61cfa8326731f41b8c887 100644
--- a/lib/red_black_tree.rb
+++ b/lib/red_black_tree.rb
@@ -1,3 +1,5 @@
+require 'atomic'
+
 class RedBlackTree
   include Enumerable
 
@@ -7,11 +9,13 @@ class RedBlackTree
     attr_reader :key, :value, :color
     attr_reader :left, :right
 
-    def initialize(key, value)
-      @key, @value = key, value
-      @left = @right = EMPTY
+    def initialize(key, value, left, right, color = :RED)
+      @key = key
+      @value = value
+      @left = left
+      @right = right
       # new node is added as RED
-      @color = :RED
+      @color = color
     end
 
     def set_root
@@ -67,14 +71,14 @@ class RedBlackTree
       case key <=> @key
       when -1
         @left = @left.insert(key, value)
-        if black? and @right.black? and @left.red? and !@left.children_both_black?
+        if black? and @right.black? and @left.red? and !@left.children_color?(:BLACK)
           ret = rebalance_for_left_insert
         end
       when 0
         @value = value
       when 1
         @right = @right.insert(key, value)
-        if black? and @left.black? and @right.red? and !@right.children_both_black?
+        if black? and @left.black? and @right.red? and !@right.children_color?(:BLACK)
           ret = rebalance_for_right_insert
         end
       else
@@ -108,7 +112,7 @@ class RedBlackTree
         end
       when 0
         deleted = self
-        ret, rebalance = delete_self
+        ret, rebalance = delete_node
       when 1
         deleted, @right, rebalance = @right.delete(key)
         if rebalance
@@ -138,8 +142,8 @@ class RedBlackTree
 
     # for debugging
     def check_height
-      lh = @left.empty? ? 0 : @left.check_height
-      rh = @right.empty? ? 0 : @right.check_height
+      lh = @left.nil?  || @left.empty? ? 0 : @left.check_height
+      rh = @right.nil? || @right.empty? ? 0 : @right.check_height
       if red?
         if @left.red? or @right.red?
           puts dump_tree(STDERR)
@@ -156,8 +160,8 @@ class RedBlackTree
 
   protected
 
-    def children_both_black?
-      @right.black? and @left.black?
+    def children_color?(color)
+      @right.color == @left.color && @right.color == color
     end
 
     def color=(color)
@@ -176,15 +180,9 @@ class RedBlackTree
       @color, other.color = other.color, @color
     end
 
-    def node_flip(other)
-      @left, other.left = other.left, @left
-      @right, other.right = other.right, @right
-      color_flip(other)
-    end
-
     def delete_min
       if @left.empty?
-        [self, *delete_self]
+        [self, *delete_node]
       else
         ret = self
         deleted, @left, rebalance = @left.delete_min
@@ -201,7 +199,7 @@ class RedBlackTree
       rebalance = false
       if black?
         if @right.black?
-          if @right.children_both_black?
+          if @right.children_color?(:BLACK)
             # make whole sub-tree 1 level lower and ask rebalance
             @right.color = :RED
             rebalance = true
@@ -217,7 +215,7 @@ class RedBlackTree
           raise 'should not happen' if rebalance
         end
       else # red
-        if @right.children_both_black?
+        if @right.children_color?(:BLACK)
           # make right sub-tree 1 level lower
           color_flip(@right)
         else
@@ -235,7 +233,7 @@ class RedBlackTree
       rebalance = false
       if black?
         if @left.black?
-          if @left.children_both_black?
+          if @left.children_color?(:BLACK)
             @left.color = :RED
             rebalance = true
           else
@@ -247,7 +245,7 @@ class RedBlackTree
           raise 'should not happen' if rebalance
         end
       else # red
-        if @left.children_both_black?
+        if @left.children_color?(:BLACK)
           color_flip(@left)
         else
           ret = balanced_rotate_right
@@ -318,7 +316,7 @@ class RedBlackTree
     # A   C      a   c
     #
     def pullup_red
-      if black? and @left.red? and @right.red?
+      if black? and children_color?(:RED)
         @left.color = @right.color = :BLACK
         self.color = :RED
       end
@@ -346,7 +344,7 @@ class RedBlackTree
       rotate_left
     end
 
-    def delete_self
+    def delete_node
       rebalance = false
       if @left.empty? and @right.empty?
         # just remove this node and ask rebalance to the parent
@@ -366,8 +364,8 @@ class RedBlackTree
         end
       else
         # pick the minimum node from the right sub-tree and replace self with it
-        new_root, @right, rebalance = @right.delete_min
-        new_root.node_flip(self)
+        deleted, @right, rebalance = @right.delete_min
+        new_root = Node.new(deleted.key, deleted.value, @left, @right, @color)
         if rebalance
           new_root, rebalance = new_root.rebalance_for_right_delete
         end
@@ -403,7 +401,7 @@ class RedBlackTree
 
       # returns new_root
       def insert(key, value)
-        Node.new(key, value)
+        Node.new(key, value, self, self)
       end
 
       # returns value
@@ -441,53 +439,57 @@ class RedBlackTree
     @default_proc = block
   end
 
+  def root
+    @root
+  end
+
   def empty?
-    @root == Node::EMPTY
+    root == Node::EMPTY
   end
 
   def size
-    @root.size
+    root.size
   end
   alias length size
 
   def each(&block)
     if block_given?
-      @root.each(&block)
+      root.each(&block)
       self
     else
-      Enumerator.new(@root)
+      Enumerator.new(root)
     end
   end
   alias each_pair each
 
   def each_key
     if block_given?
-      @root.each do |k, v|
+      root.each do |k, v|
         yield k
       end
       self
     else
-      Enumerator.new(@root, :each_key)
+      Enumerator.new(root, :each_key)
     end
   end
 
   def each_value
     if block_given?
-      @root.each do |k, v|
+      root.each do |k, v|
         yield v
       end
       self
     else
-      Enumerator.new(@root, :each_value)
+      Enumerator.new(root, :each_value)
     end
   end
 
   def keys
-    @root.keys
+    root.keys
   end
 
   def values
-    @root.values
+    root.values
   end
 
   def clear
@@ -502,7 +504,7 @@ class RedBlackTree
   alias insert []=
 
   def key?(key)
-    @root.retrieve(key) != Node::UNDEFINED
+    root.retrieve(key) != Node::UNDEFINED
   end
   alias has_key? key?
 
@@ -525,13 +527,13 @@ class RedBlackTree
   end
 
   def dump_tree(io = '')
-    @root.dump_tree(io)
+    root.dump_tree(io)
     io << $/
     io
   end
 
   def dump_sexp
-    @root.dump_sexp || ''
+    root.dump_sexp || ''
   end
 
   def to_hash
@@ -550,3 +552,297 @@ private
     end
   end
 end
+
+class ConcurrentRedBlackTree < RedBlackTree
+  class ConcurrentNode < Node
+    # direction: ~LEFT == RIGHT, ~RIGHT == LEFT
+    LEFT = -1
+    RIGHT = 0
+
+    # @Overrides
+    def insert(key, value)
+      case key <=> @key
+      when -1
+        dir = LEFT
+      when 0
+        node = new_value(value)
+      when 1
+        dir = RIGHT
+      else
+        raise TypeError, "cannot compare #{key} and #{@key} with <=>"
+      end
+      if dir
+        target = child(dir).insert(key, value)
+        node = new_child(dir, target)
+        if black? and child(~dir).black? and target.red? and !target.children_color?(:BLACK)
+          node = node.rebalance_for_insert(dir)
+        end
+      end
+      node.pullup_red
+    end
+
+    # @Overrides
+    def retrieve(key)
+      case key <=> @key
+      when -1
+        @left.retrieve(key)
+      when 0
+        @value
+      when 1
+        @right.retrieve(key)
+      else
+        nil
+      end
+    end
+
+    # @Overrides
+    def delete(key)
+      case key <=> @key
+      when -1
+        dir = LEFT
+      when 0
+        deleted = self
+        node, rebalance = delete_node
+      when 1
+        dir = RIGHT
+      else
+        raise TypeError, "cannot compare #{key} and #{@key} with <=>"
+      end
+      if dir
+        deleted, target, rebalance = child(dir).delete(key)
+        node = new_child(dir, target)
+        if rebalance
+          node, rebalance = node.rebalance_for_delete(dir)
+        end
+      end
+      [deleted, node, rebalance]
+    end
+
+  protected
+
+    def new_children(dir, node, other, color = @color)
+      dir == LEFT ? 
+        ConcurrentNode.new(@key, @value, node, other, color) :
+        ConcurrentNode.new(@key, @value, other, node, color)
+    end
+
+    def new_child(dir, node, color = @color)
+      dir == LEFT ? 
+        ConcurrentNode.new(@key, @value, node, @right, color) :
+        ConcurrentNode.new(@key, @value, @left, node, color)
+    end
+
+    def new_color(color)
+      ConcurrentNode.new(@key, @value, @left, @right, color)
+    end
+
+    def new_value(value)
+      ConcurrentNode.new(@key, value, @left, @right, @color)
+    end
+
+    def child(dir)
+      dir == LEFT ? @left : @right
+    end
+
+    # @Overrides
+    def delete_min
+      if @left.empty?
+        [self, *delete_node]
+      else
+        deleted, left, rebalance = @left.delete_min
+        node = new_child(LEFT, left)
+        if rebalance
+          node, rebalance = node.rebalance_for_delete(LEFT)
+        end
+        [deleted, node, rebalance]
+      end
+    end
+
+    # rebalance when the left/right sub-tree is 1 level lower than the right/left
+    def rebalance_for_delete(dir)
+      target = child(~dir)
+      rebalance = false
+      if black?
+        if target.black?
+          if target.children_color?(:BLACK)
+            # make whole sub-tree 1 level lower and ask rebalance
+            node = new_child(~dir, target.new_color(:RED))
+            rebalance = true
+          else
+            # move 1 black from the right to the left by single/double rotation
+            node = balanced_rotate(dir)
+          end
+        else
+          # flip this sub-tree into another type of 3-children node
+          node = rotate(dir)
+          # try to rebalance in sub-tree
+          target, rebalance = node.child(dir).rebalance_for_delete(dir)
+          raise 'should not happen' if rebalance
+          node = node.new_children(dir, target, node.child(~dir))
+        end
+      else # red
+        if target.children_color?(:BLACK)
+          # make right sub-tree 1 level lower
+          node = new_child(~dir, target.new_color(@color), target.color)
+        else
+          # move 1 black from the right to the left by single/double rotation
+          node = balanced_rotate(dir)
+        end
+      end
+      [node, rebalance]
+    end
+
+    # move 1 black from the right/left to the left/right by single/double rotation
+    def balanced_rotate(dir)
+      target = child(~dir)
+      if target.child(dir).red? and target.child(~dir).black?
+        node = new_child(~dir, target.rotate(~dir))
+      else
+        node = self
+      end
+      node = node.rotate(dir)
+      node.new_children(dir, node.child(dir).new_color(:BLACK), node.child(~dir).new_color(:BLACK))
+    end
+
+    # Right single rotation
+    # (b a (D c E)) where D and E are RED --> (d (B a c) E)
+    #
+    #   b              d
+    #  / \            / \
+    # a   D    ->    B   E
+    #    / \        / \
+    #   c   E      a   c
+    #
+    # Left single rotation
+    # (d (B A c) e) where A and B are RED --> (b A (D c e))
+    #
+    #     d          b
+    #    / \        / \
+    #   B   e  ->  A   D
+    #  / \            / \
+    # A   c          c   e
+    #
+    def rotate(dir)
+      new_root = child(~dir)
+      node = new_child(~dir, new_root.child(dir), new_root.color)
+      new_root.new_children(dir, node, new_root.child(~dir), @color)
+    end
+
+    # Pull up red nodes
+    # (b (A C)) where A and C are RED --> (B (a c))
+    #
+    #   b          B
+    #  / \   ->   / \
+    # A   C      a   c
+    #
+    # @Overrides
+    def pullup_red
+      if black? and @left.red? and @right.red?
+        new_children(LEFT, @left.new_color(:BLACK), @right.new_color(:BLACK), :RED)
+      else
+        self
+      end
+    end
+
+    # rebalance when the left/right sub-tree is 1 level higher than the right/left
+    # move 1 black from the left to the right by single/double rotation
+    #
+    # precondition: self is black and @left/@right is red
+    def rebalance_for_insert(dir)
+      node = self
+      if child(dir).child(~dir).red?
+        node = new_child(dir, child(dir).rotate(dir))
+      end
+      node.rotate(~dir)
+    end
+
+  private
+
+    # @Overrides
+    def delete_node
+      rebalance = false
+      if @left.empty? and @right.empty?
+        # just remove this node and ask rebalance to the parent
+        new_node = EMPTY_CONCURRENT
+        if black?
+          rebalance = true
+        end
+      elsif @left.empty? or @right.empty?
+        # pick the single children
+        new_node = @left.empty? ? @right : @left
+        if black?
+          # keep the color black
+          raise 'should not happen' unless new_node.red?
+          new_node = new_node.new_color(@color)
+        else
+          # just remove the red node
+        end
+      else
+        # pick the minimum node from the right sub-tree and replace self with it
+        deleted, right, rebalance = @right.delete_min
+        new_node = deleted.new_children(LEFT, @left, right, @color)
+        if rebalance
+          new_node, rebalance = new_node.rebalance_for_delete(RIGHT)
+        end
+      end
+      [new_node, rebalance]
+    end
+
+    class EmptyConcurrentNode < EmptyNode
+      # @Overrides
+      def insert(key, value)
+        ConcurrentNode.new(key, value, self, self)
+      end
+    end
+    EMPTY_CONCURRENT = ConcurrentNode::EmptyConcurrentNode.new.freeze
+  end
+
+  def initialize(default = DEFAULT, &block)
+    super
+    @root = Atomic.new(ConcurrentNode::EMPTY_CONCURRENT)
+  end
+
+  def root
+    @root.get
+  end
+
+  def empty?
+    root == ConcurrentNode::EMPTY_CONCURRENT
+  end
+
+  def clear
+    @root.set(ConcurrentNode::EMPTY_CONCURRENT)
+  end
+
+  def []=(key, value)
+    @root.update { |root|
+      root = root.insert(key, value)
+      root.set_root
+      root.check_height if $DEBUG
+      root
+    }
+  end
+  alias insert []=
+
+  def [](key)
+    value = @root.get.retrieve(key)
+    if value == Node::UNDEFINED
+      default_value
+    else
+      value
+    end
+  end
+
+  def delete(key)
+    deleted = nil
+    @root.update { |root|
+      deleted, root, rebalance = root.delete(key)
+      unless root == ConcurrentNode::EMPTY_CONCURRENT
+        root.set_root
+        root.check_height if $DEBUG
+      end
+      root
+    }
+    deleted.value
+  end
+end
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index 39358695dd034fb3ca822a16494e8666b2ab7005..0000000000000000000000000000000000000000
--- a/metadata.yml
+++ /dev/null
@@ -1,59 +0,0 @@
---- !ruby/object:Gem::Specification
-name: avl_tree
-version: !ruby/object:Gem::Version
-  version: 1.1.3
-  prerelease: 
-platform: ruby
-authors:
-- Hiroshi Nakamura
-autorequire: 
-bindir: bin
-cert_chain: []
-date: 2012-05-09 00:00:00.000000000 Z
-dependencies: []
-description: 
-email: nahi@ruby-lang.org
-executables: []
-extensions: []
-extra_rdoc_files: []
-files:
-- lib/red_black_tree.rb
-- lib/avl_tree.rb
-- bench/bench_element_size.rb
-- bench/profile.rb
-- bench/bench.rb
-- test/test_red_black_tree.rb
-- test/helper.rb
-- test/test_avl_tree.rb
-- README
-homepage: http://github.com/nahi/avl_tree
-licenses: []
-post_install_message: 
-rdoc_options: []
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
-  none: false
-  requirements:
-  - - ! '>='
-    - !ruby/object:Gem::Version
-      version: '0'
-      segments:
-      - 0
-      hash: -4094052252433988634
-required_rubygems_version: !ruby/object:Gem::Requirement
-  none: false
-  requirements:
-  - - ! '>='
-    - !ruby/object:Gem::Version
-      version: '0'
-      segments:
-      - 0
-      hash: -4094052252433988634
-requirements: []
-rubyforge_project: 
-rubygems_version: 1.8.23
-signing_key: 
-specification_version: 3
-summary: AVL tree and Red-black tree in Ruby
-test_files: []
diff --git a/test/test_avl_tree.rb b/test/test_avl_tree.rb
index 462768f9948f40ea036f6e5c91ab2347c5d19d3c..93b7f93d91e0fb188665b6a596ebca2120ed5917 100644
--- a/test/test_avl_tree.rb
+++ b/test/test_avl_tree.rb
@@ -458,6 +458,43 @@ class TestAVLTree < Test::Unit::TestCase
     assert_equal [], h.values
   end
 
+  def test_height
+    h = AVLTree.new
+    assert_equal 0, h.height
+    h[1] = true
+    assert_equal 1, h.height
+    h[2] = true
+    assert_equal 2, h.height
+    h[3] = true
+    assert_equal 2, h.height
+    h[4] = true
+    assert_equal 3, h.height
+    h[5] = true
+    assert_equal 3, h.height
+    h[6] = true
+    assert_equal 3, h.height
+    h[7] = true
+    assert_equal 3, h.height
+    h[8] = true
+    assert_equal 4, h.height
+    h.delete(8)
+    assert_equal 3, h.height
+    h.delete(7)
+    assert_equal 3, h.height
+    h.delete(6)
+    assert_equal 3, h.height
+    h.delete(5)
+    assert_equal 3, h.height
+    h.delete(4)
+    assert_equal 2, h.height
+    h.delete(3)
+    assert_equal 2, h.height
+    h.delete(2)
+    assert_equal 1, h.height
+    h.delete(1)
+    assert_equal 0, h.height
+  end
+
   if RUBY_VERSION >= '1.9.0'
     # In contrast to RadixTree, AVLTree just uses String#<=> as-is
     def test_encoding
diff --git a/test/test_red_black_tree.rb b/test/test_red_black_tree.rb
index 6f60377cdaf73ad12ad87c3d42ea871d5d52bfdc..b18716fca0eaebcab32172458262a324658b1421 100644
--- a/test/test_red_black_tree.rb
+++ b/test/test_red_black_tree.rb
@@ -1,9 +1,9 @@
 # -*- encoding: utf-8 -*-
 require File.expand_path('./helper', File.dirname(__FILE__))
 
-class TestRedBlackTree < Test::Unit::TestCase
+module RedBlackTreeTest
   def __test_random
-    h = RedBlackTree.new
+    h = create_test_target
     10000.times do |idx|
       key = rand(100)
       h[key] = key
@@ -13,7 +13,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_tree_rotate_RR
-    h = RedBlackTree.new
+    h = create_test_target
     assert_equal '', h.dump_sexp
     h['a'] = 1
     assert_equal 'a', h.dump_sexp
@@ -28,7 +28,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_tree_rotate_LL
-    h = RedBlackTree.new
+    h = create_test_target
     h['e'] = 1
     h['d'] = 2
     assert_equal '(e d)', h.dump_sexp
@@ -41,7 +41,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_tree_rotate_RL
-    h = RedBlackTree.new
+    h = create_test_target
     h['b'] = 1
     h['a'] = 2
     h['g'] = 3
@@ -57,7 +57,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_tree_rotate_LR
-    h = RedBlackTree.new
+    h = create_test_target
     h['g'] = 1
     h['b'] = 2
     h['h'] = 3
@@ -73,13 +73,13 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_aref_nil
-    h = RedBlackTree.new
+    h = create_test_target
     h['abc'] = 1
     assert_equal nil, h['def']
   end
 
   def test_empty
-    h = RedBlackTree.new
+    h = create_test_target
     h['abc'] = 0
     assert_equal nil, h['']
     h[''] = 1
@@ -89,13 +89,13 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_aref_single
-    h = RedBlackTree.new
+    h = create_test_target
     h['abc'] = 1
     assert_equal 1, h['abc']
   end
 
   def test_aref_double
-    h = RedBlackTree.new
+    h = create_test_target
     h['abc'] = 1
     h['def'] = 2
     assert_equal 1, h['abc']
@@ -103,14 +103,14 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_aset_override
-    h = RedBlackTree.new
+    h = create_test_target
     h['abc'] = 1
     h['abc'] = 2
     assert_equal 2, h['abc']
   end
 
   def test_split
-    h = RedBlackTree.new
+    h = create_test_target
     h['abcd'] = 1
     assert_equal 1, h['abcd']
     h['abce'] = 2
@@ -128,7 +128,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_split_and_assign
-    h = RedBlackTree.new
+    h = create_test_target
     h['ab'] = 1
     h['a'] = 2
     assert_equal 1, h['ab']
@@ -136,7 +136,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_push
-    h = RedBlackTree.new
+    h = create_test_target
     assert_equal 0, h.size
     h['a'] = 1
     assert_equal 1, h['a']
@@ -170,7 +170,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_different_type
-    h = RedBlackTree.new
+    h = create_test_target
     h['a'] = 1
     assert_raise(TypeError) do
       h[3.3] = 2
@@ -179,7 +179,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_leaf
-    h = RedBlackTree.new
+    h = create_test_target
     h['b'] = 1
     h['a'] = 2
     h['c'] = 3
@@ -189,7 +189,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_leaf_single_rotation
-    h = RedBlackTree.new
+    h = create_test_target
     h['b'] = 1
     h['a'] = 2
     h['d'] = 3
@@ -201,7 +201,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_leaf_single_rotation_right
-    h = RedBlackTree.new
+    h = create_test_target
     h['d'] = 1
     h['e'] = 2
     h['b'] = 3
@@ -213,7 +213,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_leaf_double_rotation
-    h = RedBlackTree.new
+    h = create_test_target
     h['b'] = 1
     h['a'] = 2
     h['e'] = 3
@@ -229,7 +229,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_leaf_double_rotation_right
-    h = RedBlackTree.new
+    h = create_test_target
     h['d'] = 1
     h['e'] = 2
     h['a'] = 3
@@ -245,7 +245,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_node_right
-    h = RedBlackTree.new
+    h = create_test_target
     h['c'] = 1
     h['b'] = 2
     h['g'] = 3
@@ -262,7 +262,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_node_left
-    h = RedBlackTree.new
+    h = create_test_target
     h['h'] = 1
     h['i'] = 2
     h['d'] = 3
@@ -279,7 +279,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_root
-    h = RedBlackTree.new
+    h = create_test_target
     h['b'] = 1
     h['a'] = 2
     h['c'] = 3
@@ -291,7 +291,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete
-    h = RedBlackTree.new
+    h = create_test_target
     h['a'] = 1
     h['ab'] = 2
     h['abc'] = 3
@@ -337,7 +337,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_right
-    h = RedBlackTree.new
+    h = create_test_target
     h['f'] = 1
     h['e'] = 2
     h['d'] = 3
@@ -383,7 +383,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_compaction_middle
-    h = RedBlackTree.new
+    h = create_test_target
     h['a'] = 1
     h['abc'] = 2
     h['bb'] = 3
@@ -398,7 +398,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_compaction_leaf
-    h = RedBlackTree.new
+    h = create_test_target
     h['a'] = 1
     h['abc'] = 2
     h['bb'] = 3
@@ -413,7 +413,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_balanced_rotate_left
-    h = RedBlackTree.new
+    h = create_test_target
     h['f'] = 1
     h['c'] = 100
     h['l'] = 1
@@ -440,7 +440,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_balanced_rotate_right
-    h = RedBlackTree.new
+    h = create_test_target
     h['i'] = 1
     h['l'] = 100
     h['c'] = 1
@@ -467,7 +467,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_delete_different_type
-    h = RedBlackTree.new
+    h = create_test_target
     h['a'] = 1
     h['abc'] = 2
     h['bb'] = 3
@@ -478,7 +478,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_each
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -493,7 +493,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_each_key
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -508,7 +508,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_each_value
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6, 'azzzzz' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -523,7 +523,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_keys
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -532,7 +532,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_values
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -541,14 +541,14 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_to_s
-    h = RedBlackTree.new
+    h = create_test_target
     h[5] = 1
     assert_equal 1, h[5]
     assert_nil h["5"]
   end
 
   def test_key?
-    h = RedBlackTree.new
+    h = create_test_target
     assert !h.key?('a')
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
@@ -559,22 +559,22 @@ class TestRedBlackTree < Test::Unit::TestCase
 
   def test_default
     assert_raise(ArgumentError) do
-      RedBlackTree.new('both') { :not_allowed }
+      create_test_target('both') { :not_allowed }
     end
 
-    h = RedBlackTree.new('abc')
+    h = create_test_target('abc')
     assert_equal 'abc', h['foo']
     assert_equal 'abc', h['bar']
     assert h['baz'].object_id == h['qux'].object_id
 
-    h = RedBlackTree.new { [1, 2] }
+    h = create_test_target { [1, 2] }
     assert_equal [1, 2], h['foo']
     assert_equal [1, 2], h['bar']
     assert h['baz'].object_id != h['qux'].object_id
   end
 
   def test_to_hash
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -583,7 +583,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_clear
-    h = RedBlackTree.new
+    h = create_test_target
     s = { 'aa' => 1, 'ab' => 2, 'bb' => 3, 'bc' => 4, 'a' => 5, 'abc' => 6 }
     s.each do |k, v|
       h[k] = v
@@ -595,7 +595,7 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_non_string_keys
-    h = RedBlackTree.new
+    h = create_test_target
     h[1.3] = 'a'
     h[4.3] = 'b'
 
@@ -603,15 +603,21 @@ class TestRedBlackTree < Test::Unit::TestCase
   end
 
   def test_values_for_empty_tree
-    h = RedBlackTree.new
+    h = create_test_target
 
     assert_equal [], h.values
   end
 
+  def test_check_height_on_empty_tree
+    h = create_test_target
+
+    assert_nothing_raised { h.root.check_height }
+  end
+
   if RUBY_VERSION >= '1.9.0'
     # In contrast to RadixTree, RedBlackTree just uses String#<=> as-is
     def test_encoding
-      h = RedBlackTree.new
+      h = create_test_target
       s = { 'ああ' => 1, 'あい' => 2, 'いい' => 3, 'いう瘢雹' => 4, 'あ' => 5, 'あいう瘢雹' => 6 }
       s.each do |k, v|
         h[k] = v
@@ -627,3 +633,19 @@ class TestRedBlackTree < Test::Unit::TestCase
     end
   end
 end
+
+class TestRedBlackTree < Test::Unit::TestCase
+  include RedBlackTreeTest
+
+  def create_test_target(*a, &b)
+    RedBlackTree.new(*a, &b)
+  end
+end
+
+class TestConcurrentRedBlackTree < Test::Unit::TestCase
+  include RedBlackTreeTest
+
+  def create_test_target(*a, &b)
+    ConcurrentRedBlackTree.new(*a, &b)
+  end
+end
diff --git a/test/test_red_black_tree_thread.rb b/test/test_red_black_tree_thread.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b0bb04e6a297ef25178d23367098b4a93922c2da
--- /dev/null
+++ b/test/test_red_black_tree_thread.rb
@@ -0,0 +1,39 @@
+# -*- encoding: utf-8 -*-
+require File.expand_path('./helper', File.dirname(__FILE__))
+
+class TestRedBlackTree < Test::Unit::TestCase
+  def test_thread
+    h = ConcurrentRedBlackTree.new
+    num = 100000
+    max = 1000
+    threads = []
+    # writers
+    2.times do
+      threads << Thread.new {
+        num.times do
+          key = rand(max)
+          h[key] = key
+        end
+      }
+    end
+    # deleters
+    2.times do
+      threads << Thread.new {
+        num.times do
+          key = rand(max)
+          h.delete(key)
+        end
+      }
+    end
+    # readers
+    2.times do
+      threads << Thread.new {
+        num.times do
+          key = rand(max)
+          h[key]
+        end
+      }
+    end
+    threads.each(&:join)
+  end
+end