How to ensure that a block runs entirely after other threads? (Thread.exclusive does not "work")

Hi, I expected that in the following example code, thread t1 would not
work until the Thread.exclusive blocks ends, but I am wrong:


t1 = Thread.new { loop do printf “.” ; sleep 0.1 end }

Thread.exclusive do
puts “entering Thread.exclusive…”
sleep 2
puts “exiting Thread.exclusive”
end

t1.join

But thread t1 runs every 0.1 seconds so I’ve don’t properly understood
the doc about Thread.exclusive. So, is there any easy way for telling
Ruby “run this block entirely without passing the GVL to other thread
in the middle of the block”?

Thanks a lot.

2012/5/15 Iñaki Baz C. [email protected]:

So, is there any easy way for telling
Ruby “run this block entirely without passing the GVL to other thread
in the middle of the block”?

Note: in my example running t1.stop / t1.wakeup would work, but that’s
not valid for me since in my real code I will not have control over
the possible existing threads.

Iñaki Baz C. [email protected] wrote:

But thread t1 runs every 0.1 seconds so I’ve don’t properly understood
the doc about Thread.exclusive. So, is there any easy way for telling
Ruby “run this block entirely without passing the GVL to other thread
in the middle of the block”?

Thread.exclusive is code smell and a sign of improper (or lack of)
locking/synchronization in your code. I don’t think it’s possible to
implement Thread.exclusive when using native threads, only with green
threads/fibers.

On Tue, May 15, 2012 at 5:36 PM, Iaki Baz C. [email protected]
wrote:

end

t1.join

But thread t1 runs every 0.1 seconds so I’ve don’t properly understood
the doc about Thread.exclusive. So, is there any easy way for telling
Ruby “run this block entirely without passing the GVL to other thread
in the middle of the block”?

Do I understand that correctly that you want to have 1 thread run
exclusively in the interpreter? If that’s the case I agree with Eric:
that’s a bad idea. You only need to synchronize access to shared
resources. If there are threads which do not access the shared
resource there is no point in blocking them.

I do not know your sharing and exclusiveness requirements but one
helpful option might be a read write lock. Or, of course, a regular
mutex. In any case you need to define in code which threads share
which resources and hence require exclusive access.

Kind regards

robert

On 16 May 2012 17:27, Robert K. [email protected] wrote:

Kind regards

robert

Keeping in mind that things like “the screen” are a resource; so if
you want to synchronise your output you can create a lock to restrict
access to STDOUT, or any printing/writing methods, or whatever is
appropriate. I find reentrant read-write locks are the easiest
synchronising mechanisms to keep straight in my head, but they could
be pretty heavy overkill for some applications.


Matthew K., B.Sc (CompSci) (Hons)
http://matthew.kerwin.net.au/
ABN: 59-013-727-651

“You’ll never find a programming language that frees
you from the burden of clarifying your ideas.” - xkcd

2012/5/16 Robert K. [email protected]:

I do not know your sharing and exclusiveness requirements but one
helpful option might be a read write lock. Or, of course, a regular
mutex. In any case you need to define in code which threads share
which resources and hence require exclusive access.

Hi, thanks to both.

First of all, as Eric said, Thread.exclusive does “nothing” in Ruby
1.9 (native threads), so I need to use something like Mutex, but that
requires cooperation from all the threads which could not be my case
(I’m coding a Ruby library rather than a final application).

But it’s ok, I’ll document that, in case the user wants to use
multiple threads, it is his responsability to syncronize them.

Thanks a lot.

On Wed, May 16, 2012 at 9:31 AM, Matthew K. [email protected]
wrote:

Keeping in mind that things like “the screen” are a resource; so if
you want to synchronise your output you can create a lock to restrict
access to STDOUT, or any printing/writing methods, or whatever is
appropriate. I find reentrant read-write locks are the easiest
synchronising mechanisms to keep straight in my head, but they could
be pretty heavy overkill for some applications.

Matthew, why do you full quote me? That’s exactly what I said.

On Wed, May 16, 2012 at 9:33 AM, Iaki Baz C. [email protected]
wrote:

First of all, as Eric said, Thread.exclusive does “nothing” in Ruby
1.9 (native threads), so I need to use something like Mutex, but that
requires cooperation from all the threads which could not be my case
(I’m coding a Ruby library rather than a final application).

But it’s ok, I’ll document that, in case the user wants to use
multiple threads, it is his responsability to syncronize them.

That’s a perfectly appropriate way to handle that: you don’t want to
incur synchronization overhead for all users even if they do not need
access from multiple threads. Even worse, there are cases where only
the user can decide which synchronization is appropriate. For example
the infamous cache idiom

if cache.include? x
y = cache.get(x)
else
y = create_y(x)
cache.put(x, y)
end

(I know, which Hash there are more elegant solutions - this is for
illustration purposes only.)

In this case you cannot guarantee consistency by internally
synchronizing all methods of “cache” if it must be avoided that two
threads invoke create_y() for the same x.

Cheers

robert

2012/5/16 Robert K. [email protected]:

cache.put(x, y)
end

(I know, which Hash there are more elegant solutions - this is for
illustration purposes only.)

In this case you cannot guarantee consistency by internally
synchronizing all methods of “cache” if it must be avoided that two
threads invoke create_y() for the same x.

100% agreed.

Thanks a lot.