Ruby has native support for thread local variables since version 2.0 . However active_support/core_ext/thread.rb implements this feature in pure ruby for support of thread locals in earlier versions of Ruby. So, I wonder why should we use mutex in _locals method:
_locals
does two things:
def _locals
# 1. Returns the local variable hash when defined
if defined?(@_locals)
@_locals
# 2. Lazily instantiates a locals hash
else
LOCK.synchronize { @_locals ||= {} }
end
end
That synchronization step is required to ensure that the @_locals
is never cleared out during first access.
Consider the following scenario:
thread = Thread.new
# Say I run this statement...
thread.thread_variable_set('a', 1)
# In parallel with this statement...
thread.thread_variable_get(:a)
Both of those methods call _locals
, and if they execute simultaneously, they may both end up at the lazy assignment step:
@_locals ||= {}
# Expands to...
unless @_locals
@_locals = {} # <-- We could end up here with both threads at the same time,
end # which jeopardizes any value that might have been set.
So imagine we had no mutex and that the setter completed execution while the getter had entered the lazy assignment step. We've effectively lost any locals we set due to a thread collision. Calling synchronize on a mutex guarantee that the block executes to completion without any such collisions.
Note that the core extension will not be loaded for versions of Ruby which support accessing thread-local variables. See the very last line:
unless Thread.instance_methods.include?(:thread_variable_set)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.