Question about synchronized

M

Matthias Kaeppler

Hi,

say I have two different methods M1 and M2 which work on the same object
O, whereas M1 is declared 'synchronized' while M2 is not.
Now imagine I start two threads A and B, which keep calling M1 and M2
respectively in an endless loop.

As far as I can tell, if M1 is called by A, a lock is acquired on O and
thus each call to M2 in B's context will result in the VM inserting B in
the wait set until M1 has finished (this is only because M1 is
synchronized).

But what if M2 is called on O in B's context /first/ (remember it's not
synchronized), and no lock is acquired on O, and while it's still
computing, the VM decides to give A the CPU?
Will M1 now be able to work on O, even though M2 hasn't finished yet?

In other words, is in my case of two functions, two threads and one
object the program only thread safe if /both/ methods M1 and M2 are
declared synchronized? And what effects could arise from one being not
not while the other is?

Thanks,
Matthias
 
V

VisionSet

Matthias Kaeppler said:
Hi,

say I have two different methods M1 and M2 which work on the same object
O, whereas M1 is declared 'synchronized' while M2 is not.
Now imagine I start two threads A and B, which keep calling M1 and M2
respectively in an endless loop.

As far as I can tell, if M1 is called by A, a lock is acquired on O and
thus each call to M2 in B's context will result in the VM inserting B in
the wait set until M1 has finished (this is only because M1 is
synchronized).

No M1 is not sync'd and can be called at any time, by any thread.
But what if M2 is called on O in B's context /first/ (remember it's not
synchronized), and no lock is acquired on O, and while it's still
computing, the VM decides to give A the CPU?
Will M1 now be able to work on O, even though M2 hasn't finished yet?

Yes, because no lock was ever obtained until M1 was called.
In other words, is in my case of two functions, two threads and one
object the program only thread safe if /both/ methods M1 and M2 are
declared synchronized? And what effects could arise from one being not
not while the other is?

As above!
 
R

Roedy Green

methods M1 and M2

Classes start with a upper case letter and methods with a lower case
one.

You have no idea how strange code that violates the Sun convention is
to people who rigidly follow it.

It is like saying a man named Barbi and a woman named Tex decided to
get married. They hired a preacher named Bowser. Their pet dog was
named Sheldon. The best Man's name was Cauliflower with cheese and
the bridemaid was Duck a Limon.

What colour tux should Sheldon wear?

see http://mindprod.com/jgloss/codingconventions.html
 
M

Matthias Kaeppler

Roedy said:
Classes start with a upper case letter and methods with a lower case
one.

You have no idea how strange code that violates the Sun convention is
to people who rigidly follow it.

It is like saying a man named Barbi and a woman named Tex decided to
get married. They hired a preacher named Bowser. Their pet dog was
named Sheldon. The best Man's name was Cauliflower with cheese and
the bridemaid was Duck a Limon.

What colour tux should Sheldon wear?

see http://mindprod.com/jgloss/codingconventions.html

You obviously completely missed my point, did you even read my post
beyond that line? ^^
I was obviously referring to an artificial setup which ought to
represent my problem. We call that abstraction.

Regards,
Matthias
 
M

Matthias Kaeppler

VisionSet said:
No M1 is not sync'd and can be called at any time, by any thread.

M1 /is/ synced, I suppose you mean M2?
Yes, because no lock was ever obtained until M1 was called.




As above!

Okay, thanks.

- Matthias
 
V

VisionSet

Matthias Kaeppler said:
You obviously completely missed my point, did you even read my post
beyond that line? ^^
I was obviously referring to an artificial setup which ought to
represent my problem. We call that abstraction.

To be fair, Roedy has a good point.
When you stare at code all day, you just don't see entities starting with a
capital as an Object.
I only let it slip because you hadn't actually written any code, but I keep
to the conventions in pros, because it means Java folk will get the meaning
more quickly.
 
S

Steve Horsley

Matthias said:
Hi,

say I have two different methods M1 and M2 which work on the same object
O, whereas M1 is declared 'synchronized' while M2 is not.
Now imagine I start two threads A and B, which keep calling M1 and M2
respectively in an endless loop.

As far as I can tell, if M1 is called by A, a lock is acquired on O and
thus each call to M2 in B's context will result in the VM inserting B in
the wait set until M1 has finished (this is only because M1 is
synchronized).
No, this is wrong. When B calls M2, it does not try to acquire
the lock, and therefore does not discover that it is already
locked by A. B (also C, D and E at the same time) is free to
enter M2 regardless of whether anyone has the lock.
But what if M2 is called on O in B's context /first/ (remember it's not
synchronized), and no lock is acquired on O, and while it's still
computing, the VM decides to give A the CPU?
Will M1 now be able to work on O, even though M2 hasn't finished yet?
Yes. Although no other threads will be able to enter M1 until A
leaves it.
In other words, is in my case of two functions, two threads and one
object the program only thread safe if /both/ methods M1 and M2 are
declared synchronized? And what effects could arise from one being not
not while the other is?

That's right.

Steve
 
J

John C. Bollinger

Matthias said:
say I have two different methods M1 and M2 which work on the same object
O, whereas M1 is declared 'synchronized' while M2 is not.
Now imagine I start two threads A and B, which keep calling M1 and M2
respectively in an endless loop.

So thread A only calls M1, and thread B only calls M2? OK.
As far as I can tell, if M1 is called by A, a lock is acquired on O and
thus each call to M2 in B's context will result in the VM inserting B in
the wait set until M1 has finished (this is only because M1 is
synchronized).

No, that's not entirely correct. Thread A does lock O's monitor once at
each entry to M1, and it unlocks the monitor once at each exit from M1,
but that has no effect on any thread invoking /unsynchronized/ method M2.
But what if M2 is called on O in B's context /first/ (remember it's not
synchronized), and no lock is acquired on O, and while it's still
computing, the VM decides to give A the CPU?
Will M1 now be able to work on O, even though M2 hasn't finished yet?

Yes. You should think of synchronization as protecting sections of code
-- either blocks or methods -- not objects. It is in fact mostly a
convenience that every object /has/ a monitor at all; the object whose
monitor you use to synchronize a particular block of code does not have
to have any particular relation to the class that owns the code.
Synchronized methods automatically synchronize on the object they are
invoked on, but with a synchronized block you specify which object's
monitor is used. This is very important.
In other words, is in my case of two functions, two threads and one
object the program only thread safe if /both/ methods M1 and M2 are
declared synchronized? And what effects could arise from one being not
not while the other is?

If both M1 and M2 are synchronized then no more than one thread will
ever execute in either one of them (collectively) at any particular
time. This may be sufficient for thread safety, but it is not certain
to be sufficient. The canonical example here is the Collections
classes: suppose I have a Collection whose methods are all synchronized.
Thread T1 gets the Collection's iterator and starts iterating through
the elements. Meanwhile, thread T2 adds an element to the Collection in
between T1's invocations of next(). The synchronization ensures that
the Collection's internal state remains consistent and means that there
is no data race in the sense that that term is used in the latest Java
language spec. The synchronization of the individual methods does not
prevent T1 from receiving a ConcurrentModificationException. The
solution in this case is to put the whole iteration inside a block
synchronized on the Collection.

To get a grip on multithreaded programming in Java it is also important
to understand the use and effects of Object.wait(), .notify(), and
..notifyAll(), and to appreciate the nondeterminism of the thread
scheduler. Those are topics for another post, however.
 
M

Matthias Kaeppler

Steve said:
No, this is wrong. When B calls M2, it does not try to acquire the lock,
and therefore does not discover that it is already locked by A. B (also
C, D and E at the same time) is free to enter M2 regardless of whether
anyone has the lock.

That's interesting. Doesn't that effectively render my synchronized
function useless in terms of atomicity, when anyone can go ahead and
call his/her unsynced methods on my object, even if I own that lock? ^^

Regards,
Matthias
 
M

Matthias Kaeppler

VisionSet said:
To be fair, Roedy has a good point.
When you stare at code all day, you just don't see entities starting with a
capital as an Object.
I only let it slip because you hadn't actually written any code, but I keep
to the conventions in pros, because it means Java folk will get the meaning
more quickly.

Heh, okay, I didn't expect anyone to be overstrained by referring to a
method in uppercase... I'll keep it in mind :)
 
M

Matthias Kaeppler

John said:
No, that's not entirely correct. Thread A does lock O's monitor once at
each entry to M1, and it unlocks the monitor once at each exit from M1,
but that has no effect on any thread invoking /unsynchronized/ method M2.

I see.
Yes. You should think of synchronization as protecting sections of code
-- either blocks or methods -- not objects. It is in fact mostly a
convenience that every object /has/ a monitor at all; the object whose
monitor you use to synchronize a particular block of code does not have
to have any particular relation to the class that owns the code.
Synchronized methods automatically synchronize on the object they are
invoked on, but with a synchronized block you specify which object's
monitor is used. This is very important.

Yes, I was aware of the difference between synchronized being used as a
statement as opposed to being used as a modifier for methods, but I
wasn't sure about the mechanics between sychronized blocks of code (or
methods) and such that aren't synchronized.
If both M1 and M2 are synchronized then no more than one thread will
ever execute in either one of them (collectively) at any particular
time. This may be sufficient for thread safety, but it is not certain
to be sufficient. The canonical example here is the Collections
classes: suppose I have a Collection whose methods are all synchronized.
Thread T1 gets the Collection's iterator and starts iterating through
the elements. Meanwhile, thread T2 adds an element to the Collection in
between T1's invocations of next(). The synchronization ensures that
the Collection's internal state remains consistent and means that there
is no data race in the sense that that term is used in the latest Java
language spec. The synchronization of the individual methods does not
prevent T1 from receiving a ConcurrentModificationException. The
solution in this case is to put the whole iteration inside a block
synchronized on the Collection.

To get a grip on multithreaded programming in Java it is also important
to understand the use and effects of Object.wait(), .notify(), and
.notifyAll(), and to appreciate the nondeterminism of the thread
scheduler. Those are topics for another post, however.

That was quite insightful, thanks.

Regards,
Matthias
 
R

Roedy Green

You obviously completely missed my point, did you even read my post
beyond that line? ^^

no, and I thought you should know why you are not getting as many
responses as you expected.
 
R

Roedy Green

Heh, okay, I didn't expect anyone to be overstrained by referring to a
method in uppercase... I'll keep it in mind :)

People who persist in doing it are usually snotty brat know-it-alls
who do it just to annoy the very people they are supposedly asking to
help them. I doubt that was your intention.

..
 
M

Matthias Kaeppler

Roedy said:
no, and I thought you should know why you are not getting as many
responses as you expected.

Are you trying to tell me that I received less responses than other
people because I used uppercase notation for a method? I hope you know
how ridiculous that sounds.
But anyway, I already told you, next time I will remember that and use
camel-case all the way to make you smile again! :D

No seriously, I actually had no expectations at all about the quantity
of responses since I rarely post here (I just don't use it as frequent
as, say, C++), but I am happy with all responses so far (and already
said so).

Best regards,
Matthias
 
R

Roedy Green

Are you trying to tell me that I received less responses than other
people because I used uppercase notation for a method?

YES!

You piss people off when you do that.

It is like top posting.
 
R

Roedy Green

Are you trying to tell me that I received less responses than other
people because I used uppercase notation for a method? I hope you know
how ridiculous that sounds.

Obviously, you got at least one less than expected because I refused
to answer your questions, and I usually answer posts..
 
J

John C. Bollinger

Matthias said:
Are you trying to tell me that I received less responses than other
people because I used uppercase notation for a method? I hope you know
how ridiculous that sounds.

I hope you will grasp that no matter how ridiculous Roedy's assertion
may sound to you, it is quite possibly true. Many newsgroup
participants (in any group) are restrictive about which posts they read,
and most are even more restrictive about which they respond to. Myself,
I doubt whether I read 25% of the posts to this group. If a post is
hard to read -- for whatever reason -- then it is likely that
considerably fewer people will bother with it than otherwise would do.

Also, taking the attitude that your post *deserves* attention, or any
particular kind of response, does not resonate well on Usenet. If I had
seen the exchange between you and Roedy before posting my response to
your original message then I might not have bothered.
 
T

Thomas G. Marshall

Roedy Green coughed up:
People who persist in doing it are usually snotty brat know-it-alls
who do it just to annoy the very people they are supposedly asking to
help them. I doubt that was your intention.

I'm not sure I see what he did as any different than saying

If person X makes Y amount of money....

He abstracted out the M1 not as the /identifier/ but the abstracted name for
it. Meta meta meta meta meta....I just don't see an issue with it.
 
T

Thomas G. Marshall

Matthias Kaeppler coughed up:
That's interesting. Doesn't that effectively render my synchronized
function useless in terms of atomicity, when anyone can go ahead and
call his/her unsynced methods on my object, even if I own that lock? ^^

There is no lock honored unless all the participants that are intended to be
locked out from each other are engaging in synchronization.

If you have

public class Hooey
{
public synchronized void m1() {...}
public synchronized void m2() {...}
public synchronized void m3() {...}
public void m4() {....}
}

then m4() is free to be called and executed without regard to the mutex.
That means it can do anything to the object. The full explanations of how
this all works is beyond the scope of a usenet post.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top