« Return to Thread: [ruby-core:20999] Supporting Thread.critical=with native threads

[ruby-core:21027] Re: Supporting Thread.critical=with native threads

by Evan Phoenix :: Rate this Message:

Reply to Author | View in Thread


On Dec 31, 2008, at 1:19 PM, David Flanagan wrote:

> Charlie, Evan, Shri:
>
> Just to be clear here, would you all agree that Thread.critical= is  
> a deprecated feature--removed in Ruby 1.9, and that your discussion  
> of it is limited to compatibility for Ruby 1.8 programs?  None of  
> you are proposing to revive it as a non-deprecated feature in your  
> implementations, are you?

Matz has pretty clearly stated that Thread.critical was an  
implementation specific feature of 1.8 that is deprecated/removed in  
1.9. I whole heartedly agree with this, since we have sufficient  
replacements to use (Mutex, Sync, etc) that are easily implemented on  
all implementations.

  - Evan

>
>
> David Flanagan
>
> Evan Phoenix wrote:
>> 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
>>>
>
>


 « Return to Thread: [ruby-core:20999] Supporting Thread.critical=with native threads