Hi all,
I learning ruby thread and faced to thread problem.
Here’s my test code that sum 1 to 1000.
–
threads = []
sum = 0
1.upto(1000) { |external|
threads << Thread.new(external) { |local|
sleep(rand(0.01))
sum = sum + local
}
}
threads.each() { |thread| thread.join() }
puts sum
I expected ‘500500’ but output is smaller than. (ex: 499864)
Please let me know what problem is.
crizin
November 17, 2010, 9:09am
2
I think that the reason of this problem is the simultaneous use of a
common resource. In your example, the common resource is the variable
sum . You need to use a Mutex object to avoid the simultaneous use of
that variable.
cf. Mutex class: http://ruby-doc.org/core/classes/Mutex.html
require ‘thread’
threads = []
sum = 0
mutex = Mutex.new
1.upto(1000) { |external|
threads << Thread.new(external) { |local|
sleep(rand(0.01))
mutex.synchronize {
sum = sum + local
}
}
}
threads.each() { |thread| thread.join() }
puts sum
2010/11/17 Jaeyong L. [email protected] :
crizin
November 17, 2010, 9:19am
3
On 11/16/2010 11:50 PM, Jaeyong L. wrote:
–
I expected ‘500500’ but output is smaller than. (ex: 499864)
Please let me know what problem is.
A race condition or race hazard is the condition of an electronics, software, or other system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events. It becomes a bug when one or more of the possible behaviors is undesirable.
The term race condition was already in use by 1954, for example in David A. Huffman's doctoral thesis "The synthesis of sequential switching circuits".
Race conditions can occur especially in logic circuits, multithrea...
You are updating a shared variable “simultaneously” in separate threads,
which is a very bad idea.
-Justin
crizin
November 17, 2010, 9:57am
4
On Wed, Nov 17, 2010 at 9:16 AM, Justin C. [email protected]
wrote:
You are updating a shared variable “simultaneously” in separate threads,
which is a very bad idea.
Absolutely correct. In this particular case using a shared resource
is not necessary since the state of that shared resource is only
accessed when all threads have terminated. One could do this as well:
threads = []
1.upto(1000) { |external|
threads << Thread.new(external) { |local|
sleep(rand(0.01))
local
}
}
sum = 0
threads.each() { |thread| sum += thread.value()}
puts sum
Kind regards
robert
crizin
November 17, 2010, 12:11pm
5
Y. NOBUOKA wrote in post #962070:
I think that the reason of this problem is the simultaneous use of a
common resource. In your example, the common resource is the variable
sum .
Or more explicitly: sum = sum + local is not an atomic operation.
Consider it as a sequence of steps:
retrieve value of ‘sum’
retrieve value of ‘local’
add them
store the result back in ‘sum’
Now think what happens when two threads are doing this together. Let’s
say the sum is currently 15, and the two threads want to add 6 and 7.
Thread A might get as far as completing steps 1-3, reading the value of
sum (15) and local (6) and computing the sum, then get switched out.
Thread B runs. It reads sum (15) and local (7), and computes the sum. It
stores 22 into ‘sum’.
Thread A now resumes. It stores 21 into ‘sum’, overwriting the value
stored by Thread B.
Regards,
Brian.