Ruby:内存中基于哈希的线程安全缓冲区?

jim*_*meh 1 ruby queue buffer thread-safety

我正在Redis支持的库中实现一种写/存储缓冲区,以将多个hincrby调用压缩为单个调用.缓冲区需要完全原子化并跨多个线程工作.

因此,我对处理线程安全问题很陌生; 是否有任何现有的库或标准化方法来实现在线程环境中正常工作的基于Hash的全局缓冲区/队列?

举个例子,缓冲区哈希就像这个伪代码一样:

buffer #=> { :ident1 => { :value_a => 1, :value_b => 4 },
       #     :ident2 => { :value_a => 2, :value_b => 3 } }

buffer[:ident1][:value_a] #=> 1

# saving merges and increments {:value_a => 2} into buffer[:ident1]
save(:ident1, {:value_a => 2})

buffer[:ident1][:value_a] #=> 3
Run Code Online (Sandbox Code Playgroud)

这个想法是在X次save调用之后,通过调用缓冲区中的save每个项来刷新缓冲区.

Phr*_*ogz 5

通常,以线程安全的方式提供对全局值的访问的方式是使用内置的Mutex类:

$buffer = {}
$bufflock = Mutex.new

threads = (0..2).map do |i|
  Thread.new do
    puts "Starting Thread #{i}"
    3.times do
      puts "Thread #{i} got: #{$buffer[:foo].inspect}"
      $bufflock.synchronize{ $buffer[:foo] = ($buffer[:foo] || 1) * (i+1) }
      sleep rand
    end
    puts "Ending Thread #{i}"
  end
end
threads.each{ |t| t.join } # Wait for all threads to complete

#=> Starting Thread 0
#=> Thread 0 got: nil
#=> Starting Thread 1
#=> Thread 1 got: 1
#=> Starting Thread 2
#=> Thread 2 got: 2
#=> Thread 1 got: 6
#=> Thread 1 got: 12
#=> Ending Thread 1
#=> Thread 0 got: 24
#=> Thread 2 got: 24
#=> Thread 0 got: 72
#=> Thread 2 got: 72
#=> Ending Thread 0
#=> Ending Thread 2
Run Code Online (Sandbox Code Playgroud)

Mutex#synchronize块内的代码是每个线程的原子; 一个线程无法进入,$bufflock直到前一个线程完成块.

另请参见:纯Ruby并发哈希