This project is now part of the RuboCop organization at rubocop/rubocop-thread_safety. Please follow development there.
Thread-safety analysis for your projects, as an extension to RuboCop.
Add this line to your application's Gemfile (using require: false as it's a standalone tool):
gem 'rubocop-thread_safety', require: falseInstall it with Bundler by invoking:
$ bundle
Add this line to your application's .rubocop.yml:
require: rubocop-thread_safety
Now you can run rubocop and it will automatically load the RuboCop
Thread-Safety cops together with the standard cops.
Install the gem:
$ gem install rubocop-thread_safety
Scan the application for just thread-safety issues:
$ rubocop -r rubocop-thread_safety --only ThreadSafety,Style/GlobalVars,Style/ClassVars,Style/MutableConstant
There are some added configuration options that can be tweaked to modify the behaviour of these thread-safety cops.
There are a few ways to improve thread-safety that stem around avoiding unsynchronized mutation of state that is shared between multiple threads.
State shared between threads may take various forms, including:
- Class variables (
@@name). Note: these affect child classes too. - Class instance variables (
@namein class context or class methods) - Constants (
NAME). Ruby will warn if a constant is re-assigned to a new value but will allow it. Mutable objects can still be mutated (e.g. push to an array) even if they are assigned to a constant. - Globals (
$name), with the possible exception of some special globals provided by ruby that are documented as thread-local like regular expression results. - Variables in the scope of created threads (where
Thread.newis called).
Improvements that would make shared state thread-safe include:
freezeobjects to protect against mutation. Note:freezeis shallow, i.e. freezing an array will not also freeze its elements.- Use data structures or concurrency abstractions from concurrent-ruby, e.g.
Concurrent::Map - Use a
Mutexor similar tosynchronizeaccess. - Use
ActiveSupport::CurrentAttributes - Use
RequestStore - Use
Thread.current[:name]
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/covermymeds/rubocop-thread_safety.
Copyright (c) 2016-2022 CoverMyMeds. See LICENSE.txt for further details.