Best way to synchronize access to a method?

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-forum.com/.

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-forum.com/\.

Just a completely un-Ruby related but Threading in general related observation.

Think in terms of complete transactions.

So you have the max now.

What are you going to do with it?

Remember, by the time you use it, it may well be wrong. So the
synchronization blocked other threads whilst you were calculating the
max value, but as soon as you have the value, myClass is can be modified
by another thread!

So, do you just want it as a rough indicator of what it was at the time you
said "get_max_value"?

Or do you need it to be exactly and every time the true max value at the
instant you use it?

In which case you have a bug, a thread race. And it doesn't matter which
language you are programming in!

So there is two approaches to this...

1) Move the synchronization out to client to synchronize both the
    get_max and the use of it.

2) Move the get_max and the use into myClass. This conforms better to
    the Law of Demeter or the Tell Don't Ask principle.

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.

···

On Tue, 11 Jul 2006, Wes Gamble wrote:

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?

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-forum.com/\.

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

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-forum.com/.

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-forum.com/\.

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-forum.com/.