# Mutex question / request

**URL:** <https://rubytalk.org/t/mutex-question-request/12754>\
**Category:** ruby-talk\
**Created:** [25 July 2004 21:06 UTC](https://rubytalk.org/t/mutex-question-request/12754 "2004-07-25T21:06:53Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian\_Schroeder](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@Brian\_Schroeder](https://rubytalk.org/u/Brian_Schroeder)\
**Post date:** [25 July 2004 21:06 UTC](https://rubytalk.org/t/mutex-question-request/12754/1 "2004-07-25T21:06:53Z")

</div>

Hello,

playing around with threads I observed, that it is impossible to lock a  
mutex twice from within the same thread. Coming from a delphi background  
I'm used to have the possibility to enter a critical section as often as I  
like, as long as I'm in the same thread. That allows for some simpler  
programming, as I can for example allow the user to read from a protected  
accessor while he has aquired the lock for some bigger operation.

To be more specific:

The following is not working:  
=== Test 1 ===  
require 'thread'

m = Mutex.new

m.synchronize do  
&nbsp;&nbsp;puts 'locked level 1'  
&nbsp;&nbsp;m.synchronize do  
&nbsp;&nbsp;&nbsp;&nbsp;puts 'level 2'  
&nbsp;&nbsp;end  
end  
=== EOF ===

I'd like to use it for this usecase:

=== usecase ===  
class A  
&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@lock = Mutex.new  
&nbsp;&nbsp;end

&nbsp;&nbsp;def x  
&nbsp;&nbsp;&nbsp;&nbsp;result = ''  
&nbsp;&nbsp;&nbsp;&nbsp;@lock.synchronize do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Do something with result  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;result  
&nbsp;&nbsp;end

&nbsp;&nbsp;def synchronize  
&nbsp;&nbsp;&nbsp;&nbsp;@lock.synchronize do yield end  
&nbsp;&nbsp;end  
end

a = A.new  
a.synchronize do  
&nbsp;&nbsp;# Do something with a  
&nbsp;&nbsp;puts a.x  
&nbsp;&nbsp;# Do some more with a  
end  
=== EOF ===

I looked into the thread library and came up with some changes that should  
implement the behaviour I want. But my knowledge of ruby threads is quite  
limited, so I'd like your feedback on how good this is. Also I'm  
interested if you think that this is a good idea, and if it should be  
proposed for inclusion in the standard library?

=== MultiMutex ===  
class MultiMutex \< Mutex  
&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@lockingthread = nil  
&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 0  
&nbsp;&nbsp;&nbsp;&nbsp;super  
&nbsp;&nbsp;end

&nbsp;&nbsp;def lock  
&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = true  
&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @lockingthread = Thread.current then  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth += 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (Thread.critical = true; @lockdepth \> 0)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@waiting.push Thread.current  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.stop  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;ensure  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = false  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;self  
&nbsp;&nbsp;end

&nbsp;&nbsp;def unlock  
&nbsp;&nbsp;&nbsp;&nbsp;return @lockdepth unless @locked  
&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = true  
&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @lockdepth \> 1 then  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth -= 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return @lockdepth  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockingthread = nil  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 0  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = @waiting.shift  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.wakeup if t  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue ThreadError  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retry  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;ensure  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = false  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;begin  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.run if t  
&nbsp;&nbsp;&nbsp;&nbsp;rescue ThreadError  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth  
&nbsp;&nbsp;end  
end  
=== EOF ===

> **···**
>
> --  
> Brian Schröder  
> [http://www.brian-schroeder.de/](http://www.brian-schroeder.de/)

---

<div class="post-metadata">

**Author:** ![Gennady1](https://avatars.discourse-cdn.com/v4/letter/g/a4c791/32.png) [@Gennady1](https://rubytalk.org/u/Gennady1)\
**Post date:** [26 July 2004 00:07 UTC](https://rubytalk.org/t/mutex-question-request/12754/2 "2004-07-26T00:07:06Z")

</div>

> Hello,
> 
> playing around with threads I observed, that it is impossible to lock a  
> mutex twice from within the same thread. Coming from a delphi background

Look at monitor.rb (comes in standard Ruby distribution). It has almost same API as Mutex, however it was designed to be re-enterable by the current owner.

> I'm used to have the possibility to enter a critical section as often as I  
> like, as long as I'm in the same thread. That allows for some simpler  
> programming, as I can for example allow the user to read from a protected  
> accessor while he has aquired the lock for some bigger operation.
> 
> To be more specific:
> 
> The following is not working:  
> === Test 1 ===  
> require 'thread'
> 
> m = Mutex.new
> 
> m.synchronize do  
> &nbsp;&nbsp;puts 'locked level 1'  
> &nbsp;&nbsp;m.synchronize do  
> &nbsp;&nbsp;&nbsp;&nbsp;puts 'level 2'  
> &nbsp;&nbsp;end  
> end  
> === EOF ===
> 
> I'd like to use it for this usecase:
> 
> === usecase ===  
> class A  
> &nbsp;&nbsp;def initialize  
> &nbsp;&nbsp;&nbsp;&nbsp;@lock = Mutex.new  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def x  
> &nbsp;&nbsp;&nbsp;&nbsp;result = ''  
> &nbsp;&nbsp;&nbsp;&nbsp;@lock.synchronize do  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Do something with result  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;result  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def synchronize  
> &nbsp;&nbsp;&nbsp;&nbsp;@lock.synchronize do yield end  
> &nbsp;&nbsp;end  
> end
> 
> a = A.new  
> a.synchronize do  
> &nbsp;&nbsp;# Do something with a  
> &nbsp;&nbsp;puts a.x  
> &nbsp;&nbsp;# Do some more with a  
> end  
> === EOF ===
> 
> I looked into the thread library and came up with some changes that should  
> implement the behaviour I want. But my knowledge of ruby threads is quite  
> limited, so I'd like your feedback on how good this is. Also I'm  
> interested if you think that this is a good idea, and if it should be  
> proposed for inclusion in the standard library?
> 
> === MultiMutex ===  
> class MultiMutex \< Mutex  
> &nbsp;&nbsp;def initialize  
> &nbsp;&nbsp;&nbsp;&nbsp;@lockingthread = nil  
> &nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 0  
> &nbsp;&nbsp;&nbsp;&nbsp;super  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def lock  
> &nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = true  
> &nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @lockingthread = Thread.current then  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth += 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (Thread.critical = true; @lockdepth \> 0)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@waiting.push Thread.current  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.stop  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;ensure  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = false  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;self  
> &nbsp;&nbsp;end
> 
> &nbsp;&nbsp;def unlock  
> &nbsp;&nbsp;&nbsp;&nbsp;return @lockdepth unless @locked  
> &nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = true  
> &nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @lockdepth \> 1 then  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth -= 1  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return @lockdepth  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockingthread = nil  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@lockdepth = 0  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = @waiting.shift  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.wakeup if t  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue ThreadError  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retry  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;ensure  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = false  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;begin  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.run if t  
> &nbsp;&nbsp;&nbsp;&nbsp;rescue ThreadError  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;@lockdepth  
> &nbsp;&nbsp;end  
> end  
> === EOF ===
> 
> --  
> Brian Schröder  
> [http://www.brian-schroeder.de/](http://www.brian-schroeder.de/)

Sincerely,  
Gennady Bystritsky

> **···**
>
> On Jul 25, 2004, at 2:06 PM, Brian Schroeder wrote:
