How do I store/access/update a thread-safe variabl

2019-08-31 14:42发布

I want to store and update an Enum in an thread-safe way in my sinatra app. I use unicorn. I tried the following:

#!/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

The view just shows $num ;)

I started the app with unicorn (4 workers) and visited http://localhost:8080/winner with my browser. I clicked on refresh several times, but the app didn't show the expected behaviour (1,2,3,4,5,...) it instead showed random numbers (1,1,2,1,2,3,2,3,2,3,4,...)

so how do I get this thread-safe? :D (sorry for my bad english)

1条回答
Viruses.
2楼-- · 2019-08-31 15:03

Your issue isn't so much thread safety (although there is a slight race condition here - use a mutex rather than your $locked variable) as the fact that each unicorn worker is a separate process.

Each of these processes has a separate set of global variables, so the code you've written fundamentally can't work, no matter how much synchronisation you add to each process.

The ususal way to approach this would be to store the number in some shared datastore, for example a database like mysql, mongo, redis or even memcached. The last 3 of those have a specific atomic create or increment operation, but you can do this in a relational database too.

查看更多
登录 后发表回答