Without this the following could happen:
1. Thread A acquires the lock and sets the ownership to A.
2. Thread A yields and returns
3. Thread B tries to acquire the lock
4. At this exact moment Thread A calls the "synchronize" method again
and sees that the "owner" variable is still set to Thread A
5. Both thread A and B can now access the underlying data in parallel,
possibly leading to corrupted objects
This can be demonstrated using the following script:
require 'oga'
lru = Oga::LRU.new(64)
threads = 50.times.map do
Thread.new do
loop do
number = rand(100)
lru[number] = number
end
end
end
threads.each(&:join)
Run this for a while on either JRuby or Rubinius and you'll end up with
errors such as "ConcurrencyError: Detected invalid array contents due to
unsynchronized modifications with concurrent users" on JRuby or
"ArgumentError: negative array size" on Rubinius.
Resetting the owner variable ensures the above can never happen. Thanks
to @chrisseaton for bringing this up earlier today.
|
||
|---|---|---|
| .. | ||
| oga | ||
| oga.rb | ||