Created
May 31, 2017 01:56
-
-
Save bebebebebe/d9f5c8ac768bcca5d1ff21b0d6c46b96 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HashRace | |
def initialize | |
@clients = {} | |
50.times {add_client} | |
end | |
def call | |
Thread.new do | |
purge | |
end | |
main | |
end | |
private | |
def main | |
i = 0 | |
loop do | |
snooze | |
if rand(2) == 1 | |
k = add_client | |
puts "new! #{k}" | |
end | |
snooze | |
@clients.each { |key, client| | |
puts "* #{i} hi #{key}" | |
} | |
puts '' | |
i += 1 | |
end | |
end | |
def purge | |
loop do | |
snooze | |
@clients.each { |key, client| | |
snooze | |
if rand(10) == 1 | |
puts "* deleting key: #{key}" | |
@clients.delete(key) | |
end | |
} | |
end | |
end | |
def add_client | |
k = rand_string | |
v = rand_string | |
@clients[k] = v | |
k | |
end | |
def rand(n) | |
[*1..n].sample | |
end | |
def snooze | |
sleep (1.0 / ([*1..5].sample)) | |
end | |
def rand_string | |
(0...8).map { ('A'.ord + rand(26)).chr }.join | |
end | |
end | |
t = HashRace.new | |
t.() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an example to illustrate a race condition that can occur between two threads. Running it (eventually) leads to an error
hash_race.rb:51:in `add_client': can't add a new key into hash during iteration (RuntimeError)
.There are two threads: a main thread that occasionally adds a new item ("client") to a hash and iterates over the hash to print out names of clients in the hash; and a purge thread that iterates over the hash of clients and occasionally deletes an element.
The problem occurs when the main thread adds an element to the hash while the purge thread is iterating over it. One way to solve this is by using a mutex, like this.
Here's some sample output: