[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Best way to synchronize access to a method?

Wes Gamble

7/10/2006 8:26:00 PM

All,

I'm reading through the Pickaxe book on synchronization and threading.
I want to have a method that will basically put a MAX() value from a
table and I want to ensure that two threads don't execute this code at
the same time.

I'm thinking I can just have my object descend from Monitor (< Monitor)
and then put "synchronize" around the relevant code, like so:

class myClass < Monitor
...

def get_max_value
synchronize { max_value = do_select_to_get_max_value }
max_value
end

This should work just fine - correct?

Thanks,
Wes

--
Posted via http://www.ruby-....

7 Answers

Wes Gamble

7/10/2006 8:32:00 PM

0

Wes Gamble wrote:
> All,
>
> I'm reading through the Pickaxe book on synchronization and threading.
> I want to have a method that will basically put a MAX() value from a
> table and I want to ensure that two threads don't execute this code at
> the same time.
>
> I'm thinking I can just have my object descend from Monitor (< Monitor)
> and then put "synchronize" around the relevant code, like so:
>
> class myClass < Monitor
> ...
>
> def get_max_value
> synchronize { max_value = do_select_to_get_max_value }
> max_value
> end
>
> This should work just fine - correct?
>
> Thanks,
> Wes

There is an admonition in the Pickaxe book that says "In both the class
form and when including MonitorMixin in an existing class it is
essential to invoke super in the class's initialize method."

I want my sychronization to occur in a class method. So that would seem
to obviate the need for the super in the "initialize" block. Am I
correct?

Thanks,
Wes

--
Posted via http://www.ruby-....

Wes Gamble

7/10/2006 9:02:00 PM

0

Wes Gamble wrote:
> Wes Gamble wrote:
>> All,
>>
>> I'm reading through the Pickaxe book on synchronization and threading.
>> I want to have a method that will basically put a MAX() value from a
>> table and I want to ensure that two threads don't execute this code at
>> the same time.
>>
>> I'm thinking I can just have my object descend from Monitor (< Monitor)
>> and then put "synchronize" around the relevant code, like so:
>>
>> class myClass < Monitor
>> ...
>>
>> def get_max_value
>> synchronize { max_value = do_select_to_get_max_value }
>> max_value
>> end
>>
>> This should work just fine - correct?
>>
>> Thanks,
>> Wes
>
> There is an admonition in the Pickaxe book that says "In both the class
> form and when including MonitorMixin in an existing class it is
> essential to invoke super in the class's initialize method."
>
> I want my sychronization to occur in a class method. So that would seem
> to obviate the need for the super in the "initialize" block. Am I
> correct?
>
> Thanks,
> Wes


Yeah, I definitely want the synchronization at the class level - do I
extend the class object directly instead of doing an "include
MonitorMixin"?

Wes

--
Posted via http://www.ruby-....

Simon Kröger

7/10/2006 9:04:00 PM

0

Wes Gamble wrote:
> Wes Gamble wrote:
>> All,
>>
>> I'm reading through the Pickaxe book on synchronization and threading.
>> I want to have a method that will basically put a MAX() value from a
>> table and I want to ensure that two threads don't execute this code at
>> the same time.
>>
>> I'm thinking I can just have my object descend from Monitor (< Monitor)
>> and then put "synchronize" around the relevant code, like so:
>>
>> class myClass < Monitor
>> ...
>>
>> def get_max_value
>> synchronize { max_value = do_select_to_get_max_value }
>> max_value
>> end
>>
>> This should work just fine - correct?
>>
>> Thanks,
>> Wes
>
> There is an admonition in the Pickaxe book that says "In both the class
> form and when including MonitorMixin in an existing class it is
> essential to invoke super in the class's initialize method."
>
> I want my sychronization to occur in a class method. So that would seem
> to obviate the need for the super in the "initialize" block. Am I
> correct?
>
> Thanks,
> Wes

You have several problems in your code you may want to look at before thinking
about Threads:

* myClass has to be spelled MyClass (see Constants in Ruby)

* get_max_value isn't a class method (use self.get_max_value if you want such)

* max_value is only defined inside the block, so you get
"undefined local variable or method `max_value' for MyClass:Class"

* if you define it as class method the interpreter will show you
"undefined method `synchronize' for MyClass:Class" because synchronize
isn't a class method

* most of the time when the documentation is saying "it is essential to..."
it is there for a reason

I don't want to be harsh, but it would be nice to let the interpreter find
the obvious bugs it is able to find.

maybe that is what you want:

require 'thread'

class MyClass
@@mutex = Mutex.new

def self.do_select_to_get_max_value;
42
end

def self.get_max_value
@@mutex.synchronize do
return do_select_to_get_max_value
end
end
end

p MyClass::get_max_value

cheers

Simon



Wes Gamble

7/10/2006 9:11:00 PM

0

Simon Kröger wrote:
> Wes Gamble wrote:
>>>
>>> Thanks,
>> Thanks,
>> Wes
>
> You have several problems in your code you may want to look at before
> thinking
> about Threads:
>
> * myClass has to be spelled MyClass (see Constants in Ruby)
>
> * get_max_value isn't a class method (use self.get_max_value if you want
> such)
>
> * max_value is only defined inside the block, so you get
> "undefined local variable or method `max_value' for MyClass:Class"
>
> * if you define it as class method the interpreter will show you
> "undefined method `synchronize' for MyClass:Class" because synchronize
> isn't a class method
>
> * most of the time when the documentation is saying "it is essential
> to..."
> it is there for a reason
>
> I don't want to be harsh, but it would be nice to let the interpreter
> find
> the obvious bugs it is able to find.
>
> maybe that is what you want:
>
> require 'thread'
>
> class MyClass
> @@mutex = Mutex.new
>
> def self.do_select_to_get_max_value;
> 42
> end
>
> def self.get_max_value
> @@mutex.synchronize do
> return do_select_to_get_max_value
> end
> end
> end
>
> p MyClass::get_max_value
>
> cheers
>
> Simon


Simon,

Thanks for the feedback. The code below appears to work. Do you agree
that the code will be sychronized on the class object itself?

=====================

require 'monitor'

class Job < ActiveRecord::Base
self.extend(MonitorMixin)

....

public
def self.get_next_job_number
max_value = nil
synchronize {
max_value = self.find(:first, :select => 'MAX(AbsJobNumber) AS
max').max
}
max_value.to_i + 1
end
end

--
Posted via http://www.ruby-....

Wes Gamble

7/10/2006 9:19:00 PM

0

I also just realized that I really need to synchronize the select and
subsequent insert so I will probably handle that in another class.

However, I believe this code would work as fas as class synchronization.

Wes

--
Posted via http://www.ruby-....

John Carter

7/10/2006 11:26:00 PM

0

Wes Gamble

7/10/2006 11:47:00 PM

0

John,

Thanks - I realized that a while ago, and I synchronized the use of the
id along with the get, so I believe all is well now.

WG

--
Posted via http://www.ruby-....