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

标签 ruby thread-safety queue buffer

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

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

举个例子,缓冲区哈希的工作方式类似于以下伪代码:

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

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

最佳答案

一般来说,以线程安全的方式提供对全局值的访问的方法是使用内置的 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

Mutex#synchronize 内的代码块对于每个线程都是原子的;在前一个线程处理完该 block 之前,一个线程无法进入 $bufflock

另请参阅:Pure-Ruby concurrent Hash

关于Ruby:内存中基于哈希的线程安全缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5666751/

相关文章:

multithreading - Perl 队列和线程

Python 多处理队列并没有让所有的工作人员都忙碌起来

c++ - 使用赋值运算符的队列的深拷贝

java - 使用其他类中的公共(public)静态 HashTable 的同步方法。我怎样才能使这个方法线程安全?

ruby - 我如何做这个简单的 Ruby 循环?

mysql - 在 ruby​​ on Rails 上创建具有多个关联的对象

ruby-on-rails - 两个日期之间的小时数 - Ruby

ruby - 用Ruby中的哈希值总结对象区域

delphi - 线程读取数据的关键部分

java - 如何杀死或停止java applet中的其他线程