On Dec 30, 2008, at 11:55 PM, Charles Oliver Nutter wrote:
> Shri Borde wrote:
>> Yes, Thread#kill and Thread#raise can be implemented in IronRuby by
>> using System.Threading.Thread.Abort (
http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx
>> ). It is fragile (like you say, its impossible to support such
>> operations reliably on native threads), and can be deferred
>> indefinitely under some circumstances. So I think we ideally need
>> to use both Thread.Abort and checkpoints.
>
> As under the JVM (and under any system with parallel-executing
> threads) System.Threading.Thread.Abort is provably unsafe, so if
> that's a concern you'll definitely need to checkpoint to support
> Ruby's Thread#raise and Thread#kill.
>
>> About Thread.critical, you said:
>>> Scripts that use critical= tend to expect that they're
>>> guaranteeing more
>>> than just the code in the critical section. For example, if they're
>>> initializing an instance variable they expect nobody else will
>>> access it
>>> during initialization
>> It would seem such code will not work even with MRI. If thread 1
>> sets Thread.critical=true and starts initializing the instance
>> variable, and if thread 2 is accessing the instance variable
>> without setting Thread.critical=true, then couldn't thread 2 run
>> into a problem even if its not scheduled, since it could be
>> anywhere in the middle of accessing the instance variable? To be
>> fully correct, wouldn't thread 2 have to set Thread.critical=true,
>> even on MRI?
>
> Once critical=true is set in a thread, all current threads will be
> taken out of scheduling, so in theory they would not even get the
> opportunity to access any instance variables.
The way that I talk about what Thread.critical does is manipulate the
preemptive Thread scheduler. So, it inhibits Threads from switching
"randomly" at any point. Instead, Threads can only be scheduled
explicitly. This means via Thread methods (inspect, value, join, run),
as well as some IO methods that explicitly switch Threads.
So, to use terms that people working with green threads use:
"Thread.critical = false" == preemptive scheduling enabled
"Thread.critical = true" == cooperative scheduling enabled
Obviously the idea with using cooperative scheduling is that the user
knows what operations cause Threads to switch. Sadly in MRI, that
knowledge completely known.
>
>
> I'll grant that it's pretty fuzzy; I think people use
> Thread.critical= in a lot of cases simply because they don't really
> know what they're doing. If critical= could be specified as simply a
> thread-reentrant lock against a special global mutex, it would
> probably be reasonable. As it is, the implications are far greater
> than simply a critical section, since it not only prevents other
> existing threads from running that given piece of code, but also
> from running *at all*, and code has been written, released, and
> tested with that assumption.
>
>> By the way, what is the level of atomicity supported by MRI? For
>> example, CPython uses the global interpreter lock (GIL) for each
>> bytecode. However, since MRI does not compile to bytecode, is the
>> AST nodes the correct level of atomicity?
>
> The AST node is not a fine enough measure of atomicity; for example,
> for a += b, there's a couple levels of node granularity, but
> obviously the outermose "op assignment" can't be atomic. And when it
> comes down to that, a large number of nodes are dependent on making
> method calls, which usually can't be guaranteed atomic. I think it
> needs to be considered on a case-by-case basis. JRuby guarantees
> instance vars can be accessed and modified concurrently, for
> example, but makes no guarantees about @a += b producing the result
> you expect in a multi-threaded environment.
>
> - Charlie
>