I'm trying to recreate a race condition in a test, so I can try out some solutions. I find that in the threads I create in my test, ActiveRecord always returns 0 for counts and nil for finds. For example, with 3 rows in the table "foos":
it "whatever" do
puts Foo.count
5.times do
Thread.new do
puts Foo.count
end
end
end
will print
3
0
0
0
0
0
test.log shows the expected query, the expected 6 times:
SELECT count(*) AS count_all FROM `active_agents`
Any idea what's going on here?
Dissecting Ruby on Rails 5 - Become a Professional Developer Often on a single CPU machine, multiple threads are not actually executed in parallel, but parallelism is simulated by interleaving the execution of the threads. Ruby makes it easy to write multi-threaded programs with the Thread class.
The Ruby Interpreter is single threaded, which is to say that several of its methods are not thread safe. In the Rails world, this single-thread has mostly been pushed to the server.
A single thread executes on one CPU core, so if you write a ruby program, then it is executed only one core of CPU and if you have quad-core CPU then other 3 cores are not utilize to execute your ruby program. Threading makes ruby program to utilize more memory and CPU to execute faster and achieve concurrency.
Calling Thread. join blocks the current (main) thread. However not calling join results in all spawned threads to be killed when the main thread exits.
I'm assuming ActiveRecord opens a dedicated database connection for each thread. Since each RSpec example is wrapped inside a transaction, the other threads might not see the changes.
Try disabling transactional fixtures for that spec.
describe "thread test" do
self.use_transactional_fixtures = false
it "whatever" do
puts Foo.count
5.times do
Thread.new do
puts Foo.count
end
end
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With