Hello fellow rubyists,
Matz has occasionally expressed his worries about the synchronization
primitive used in Ruby today. He asked for suggestions regarding alternate
schemes, and guess what, I wrote one. The following discusses object locks,
a concept known from Java and others. These object locks would replace the
current Thread.critical notation.
I have no prototype implementation of these ideas. This text is intended as
a basis for discussion to flesh things out.
I've tried to define things as concise as possible, but given the fact that
English is not my native tongue, ambiguities may remain. Please abide with
me.
Michel
1. Semantics
Every instance of class Object (and derivatives) can have a lock, or binary
semaphore, associated with it. When a method is called on an object that is
declared synchronized, or a method declared synchronized is called on an
object, or an object lock is explicitly obtained from within a member
method, the object becomes locked. The class or method effectively defines
a closure within which the lock is held. As soon as the closure finishes,
the lock is released. All further access to an instance is blocked as long
as the object lock is taken. When a thread calls a method on an instance
that is locked it is suspended, and other threads are eligible to run. Once
the object lock is released, the suspended threads waiting for that
specific lock are rescheduled.
As an optimization measure, object locks could only be associated with an
instance once a synchronization feature is used within the scope of that
instance.
Backward compatibility with the current semantics could be achieved by
defining `Thread.critical = false|true' as a method obtaining or releasing
the object lock for the instance that is in scope at the time of the call.
(But as the notion of a critical section is abstracted away from a thread,
some code `refactoring' ;) might be a better idea.)
2. Syntax
For entire classes (i.e., declare implicit synchronization semantics for
all methods in a class):
class synchronized Queue
...
end
For methods (i.e., declare implicit synchronization semantics for one
method):
class Queue
def synchronized enqueue
...
end
end
Explicit synchronization in methods:
def foo
self.synchronize{ # execute block with object lock held
}
synchronize{ # ditto, a shorthand for the above
}
foo.synchronize{ # use the object lock of `foo', which can be an
# instance of any Object (derivative)
}
end
Of course the declaration
def synchronized foo
end
is equivalent to the explicit
def foo
synchronize{
}
end
and could very well be implemented that way.
The proposed syntax requires a new keyword `synchronized', and a new method
`synchronize' on class Object. For brevity, the keyword `sync' and method
Object.sync could be considered.
Finally some code to get acquainted:
class sync Semaphore
def wait
...
end
def signal
...
end
end
or
class Semaphore
def sync signal
...
end
def sync wait
...
end
end
or
class Semaphore
def signal
sync{
...
}
end
def wait
sync{
...
}
end
end