multithreading - Ruby - Using a Mutex to keep threads from stopping prematurely -
I am writing a Ruby application (Ruby v2.1.3p242 x86_64 in Linux) which will repeatedly process online data and To store things in a database, I have multiple threads running simultaneously and I am working to stop all threads at command and completely while lifting exceptions from a thread.
The issue is that some threads will continue to run many code after the #do_stuff
which is said after the saver.stop
. After all, they are closed, but after the rest are closed I see some thread going 10-50 times.
Each threads' Mute X is locked before each recurrence and unlocks later. Code, @ mutex.synchronize {kill}
is running on every thread when called server.stop
. This should kill the thread immediately after its next recurrence, but it does not seem like this.
Edit:
works as a code, so if you wish, do not hesitate to test it. In my tests, after calling server.stop
30 seconds and several minutes to stop all threads, note that each transfer takes between 1-3 seconds. I used the following to test the code (in the same directory while using Ruby-I.
):
requires 'benchmark' The 'server' = Server puts the new s.start benchmark. Measure {s.stop}
Here is the code:
server.rb:
Requires a class of server / fiber_thread class; Server Thread = 8 Entry_Reader: Start Thread Def start @ threads = [] and start def create_threads end def stop @ threads.map {| T | Thread.new {t.stop}} .each (more: join) @ threads = [] end personalized def _ threads THREADS.times do | I | @ Threads & lt; & Lt; FetcherThread.new (number: i + 1) end-endserver / fetcher_thread.rb:
class server class FetcherThread & lt; Thread attr_reader: mutex def initialize (opts = {}) @mutex = mute x.new @number = opts [: number] || 0 Super Do Loop do @ mutex.synchronize {do_stuff} End end def def @ mutex.synchronize {kill} End personal def do_stuff debugging "# {time_to_sleep = rand * 2 + 1} sleeping for seconds" sleep time_to_sleeps end Def debug (message) $ stderr.print "thread ## {@ number}: # {message} \ n" end and end
There is no guarantee that the thread will receive the mute before the next recurrence of the call stop
loop. It is fully up to Ruby and operating system scheduling, and some OS () do not implement a FIFO scheduling algorithm, but keep in mind other factors to optimize performance.
You can estimate it more to avoid the kill
and by using a variable to exit the loop cleanly, then you can only copy the code Around the mute x must be wrapped, which is the variable
class server class FetcherThread & lt; Thread attr_reader: mutex def initialize (opts = {}) @mutex = mute x.new @number = opts [: number] || 0 Until the super stop? Do_stuff end end end def mutex.synchronize {@stop = true} end DEF stopped? Mutex.synchronize {@stop} end # ... and end
Comments
Post a Comment