如何在Sinatra应用程序(+ unicorn)中存储/访问/更新线程安全变量?

时间:2012-10-08 15:48:57

标签: ruby thread-safety sinatra

我想在我的sinatra应用程序中以线程安全的方式存储和更新Enum。我用独角兽。我尝试了以下方法:

#!/usr/bin/ruby

require 'sinatra'

$locked = false
$num = 0
class App < Sinatra::Base
  before do
    while $locked do end
    $locked = true
  end

  after do
    $locked = false
  end

  get "/wait" do
    sleep 10
    $num += 1
    erb :display
  end

  get "/winner" do
    $num += 1
    erb :display
  end
end

视图只显示$ num;)

我用独角兽(4名工作人员)启动了应用程序,并使用浏览器访问了http://localhost:8080/winner。 我点击刷新几次,但应用程序没有显示预期的行为(1,2,3,4,5,...)它显示随机数字(1,1,2,1,2,3, 2,3,2,3,4,...)

那么如何让这个线程安全呢? :d (抱歉我的英语不好)

1 个答案:

答案 0 :(得分:1)

你的问题不是线程安全(尽管这里有一个轻微的竞争条件 - 使用互斥锁而不是你的$ locked变量)因为每个独角兽工作者都是一个独立的过程。

这些进程中的每一个都有一组独立的全局变量,因此无论您为每个进程添加多少同步,您从根本上编写的代码都无法工作。

解决这个问题的方法是将数字存储在某些共享数据存储区中,例如mysql,mongo,redis甚至memcached等数据库。其中最后3个具有特定的原子创建或增量操作,但您也可以在关系数据库中执行此操作。