Threads and wait() on objects

I was under the impression that when a thread of execution calls wait() on an object, it releases only specific locks. That is, the thread will not release "all" of it's locks. Only the lock that the thread holds, and must hold, for the object upon which the wait method is invoked.

So to say that a thread which calls wait() on an object releasesall its locks, this in inaccurate right?

Thanks for any feedback.

[440 byte] By [nantucketa] at [2007-10-2 13:24:25]
# 1

> I was under the impression that when a thread of

> execution calls wait() on an object, it releases only

> specific locks. That is, the thread will not release

specifically only 1 lock: the lock on the object whose wait() method has been called. This is necessary since if it stayed locked it would be impossible to call notify() on it.

tjacobs01a at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 2
...which is frequently, in my experience, the cause of deadlocks: synchronizing on two objects at once. I take special steps to avoid that anymore. :)Just my 2c. ;)
tvynra at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 3

> ...which is frequently, in my experience, the cause

> of deadlocks: synchronizing on two objects at once.

> I take special steps to avoid that anymore. :)

>

> Just my 2c. ;)

I've never come across a situation where I've needed or wanted to synchronize on more than one object. I'm curious where this would be needed, is there an example you could give?

kablaira at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 4

> > I was under the impression that when a thread of

> > execution calls wait() on an object, it releases

> only

> > specific locks. That is, the thread will not

> release

>

> specifically only 1 lock: the lock on the object

> whose wait() method has been called. This is

> necessary since if it stayed locked it would be

> impossible to call notify() on it.

Thanks for the confirmation. That's what I thought. When wait() is called on the object, the thread releases the lock for that object.

nantucketa at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 5

> > ...which is frequently, in my experience, the

> cause

> > of deadlocks: synchronizing on two objects at

> once.

> > I take special steps to avoid that anymore. :)

> >

> > Just my 2c. ;)

>

> I've never come across a situation where I've needed

> or wanted to synchronize on more than one object.

> I'm curious where this would be needed, is there an

> n example you could give?

I am going to try and give an example so just bear with me here. It's a bit simplified and a bit contrived but hopefully you'll see the issue.

Okay I have a market where I have two stalls. One stall sells apples and the other stall sells baskets.

Customers come and can buy apples or baskets. OR they can request a basket of apples from either stall. (Okay this is the contrived part but I'm trying to get a transactional idea across here so please don't jsut how stupid it seems... I know it's dumb but it's an example)

Now in our program each stall is an object and each customer is a thread that comes along and synchonizes on the stall while they get their stuff.

The problem comes when two customers (threads) come along and both ask for baskets of apples at the same time. Because when you ask for a basket of apple one stall asks the other (through a synchronized method) to give him what he needs. So if one customer asks at the apple stall and the other at the basket stall the resulting deadlock is....

Customer a - > lock on apple stall - > waiting for lock on basket stall

Customer b -> lock on basket stall -> waiting for lock on apple stall

In any transactional system I think you can encounter this dilemma because there is a need for escalating locks in order to garauntee the atomicity of your transaction. So you have to come up with a way to detect that you can in fact get a lock or that deadlock has occurred and take appropriate action.

All in all avoid it if you can but when it comes down to a scenario like that I don't know how one can just easily plan around it. But maybe I am bonkers.

nantucketa at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 6
Have a separate object to lock on that's specifically for baskets of apples. Should work out then.
myjavasticka at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 7

> I am going to try and give an example so just bear

> with me here. It's a bit simplified and a bit

> contrived but hopefully you'll see the issue.

>

> Okay I have a market where I have two stalls. One

> stall sells apples and the other stall sells

> baskets.

>

> Customers come and can buy apples or baskets. OR they

> can request a basket of apples from either stall.

> (Okay this is the contrived part but I'm trying to

> get a transactional idea across here so please don't

> jsut how stupid it seems... I know it's dumb but it's

> an example)

>

> Now in our program each stall is an object and each

> customer is a thread that comes along and synchonizes

> on the stall while they get their stuff.

>

> The problem comes when two customers (threads) come

> along and both ask for baskets of apples at the same

> time. Because when you ask for a basket of apple one

> stall asks the other (through a synchronized method)

> to give him what he needs. So if one customer asks at

> the apple stall and the other at the basket stall the

> resulting deadlock is....

>

> Customer a - > lock on apple stall - > waiting for

> lock on basket stall

> Customer b -> lock on basket stall -> waiting for

> lock on apple stall

>

> In any transactional system I think you can encounter

> this dilemma because there is a need for escalating

> locks in order to garauntee the atomicity of your

> transaction. So you have to come up with a way to

> detect that you can in fact get a lock or that

> deadlock has occurred and take appropriate action.

>

> All in all avoid it if you can but when it comes down

> to a scenario like that I don't know how one can

> just easily plan around it. But maybe I am bonkers.

I see your point, but why can't the apple and basket stalls delegate to a third party responsible for it? For example, if they both call a ComboStall.getBasketOfApples() which is synchronized then even if it has to get locks on both apple and basket it shouldn't deadlock. I'm sure there are cases where this isn't feasible, but it just seems like the requirement exposes a design flaw.

kablaira at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 8

> I see your point, but why can't the apple and basket

> stalls delegate to a third party responsible for it?

> For example, if they both call a

> a ComboStall.getBasketOfApples() which is

> synchronized then even if it has to get locks on both

> apple and basket it shouldn't deadlock. I'm sure

> there are cases where this isn't feasible, but it

> just seems like the requirement exposes a design flaw.

The problem is that seems a brilliant solution (I know because I thought of it previously when I had this issue) but unfortunatley actually doesn't do anything useful.

All that that ultimatley does is...

Thread a -> lock on apple stall - > lock on AppleBasketDelegate - >waiting for lock on basket stall

Thread b -> lock on basket stall -> waiting for lock on AppleBasketDelegate

kablaira at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 9

> > there are cases where this isn't feasible, but it

> > just seems like the requirement exposes a design

> flaw.

>

Just to address this specifically. It may seem like that and I do agree that most often it would be but in some cases it isn't.

As an example (that I used to help myself work through my particular problem) consider a relational database. Tables can be accessed indepently and together (joins).

There are times when data and objects can be viewed, accessed and used independently of each other but they have relationships which have to be enforced between them.

I dunno. I think so. I know that rdbms with transactions have all sorts of complexity for handling deadlocks. Is everybody crazy? I tend to think no....but further feedback is warmly invited and appreciated.

kablaira at 2007-7-13 11:03:04 > top of Java-index,Java Essentials,New To Java...
# 10

> Have a separate object to lock on that's specifically

> for baskets of apples. Should work out then.

That object still has to lock on both apples and baskets.

You can obtain multiple locks without fear of deadlock as long as all threads obtain the locks in the same order. Of course, even in that situation, if multiple threads call wait(), and call it on different object, it might be possible to get into a deadlock (I'm not sure, and don't feel like working it out right now).

By the way, Max, I thought that was a really good example. Way better than I could have come up with.

jverda at 2007-7-13 11:03:05 > top of Java-index,Java Essentials,New To Java...
# 11

> That object still has to lock on both apples and baskets.

Yes, but then it avoids deadlock by making sure that, like you said, the locks are obtained in the same order. I guess I didn't make myself too clear.

class AppleStall {

synchronized Apple getApple() {

//stuff

}

}

class BasketStall {

synchronized Basket getBasket() {

//stuff

}

}

class ComboStall {

AppleStall apples;

BasketStall baskets;

synchronized Basket getBasketOfApples() {

Basket basket = baskets.getBasket();

basket.add(apples.getApples());

return basket;

}

}

myjavasticka at 2007-7-13 11:03:05 > top of Java-index,Java Essentials,New To Java...
# 12

> > Have a separate object to lock on that's

> specifically

> > for baskets of apples. Should work out then.

>

> That object still has to lock on both apples and

> baskets.

If the Apples and Baskets code that handled someone asking for both was unsynchronized and forwarded to a third object then it shouldn't be a problem. The third object will always attempt it in the same order. Granted, in a complex system it can get real ugly real fast.

kablaira at 2007-7-13 11:03:05 > top of Java-index,Java Essentials,New To Java...
# 13

> > > Have a separate object to lock on that's

> > specifically

> > > for baskets of apples. Should work out then.

> >

> > That object still has to lock on both apples and

> > baskets.

>

> If the Apples and Baskets code that handled someone

> asking for both was unsynchronized and forwarded to a

> third object then it shouldn't be a problem. The

> third object will always attempt it in the same

> order. Granted, in a complex system it can get real

> ugly real fast.

Not a problem, and it does help ensure you get the same order. It doesn't avoid syncing on both though. Or syncing on a single lock that is also synced on when getting just an apple or just a basket.

jverda at 2007-7-13 11:03:05 > top of Java-index,Java Essentials,New To Java...
# 14
Yeah, but it's still impossible to have deadlock. Throw in a wait() and notify() and you're in trouble.
kablaira at 2007-7-13 11:03:05 > top of Java-index,Java Essentials,New To Java...
# 15
> Yeah, but it's still impossible to have deadlock.I know.I think I thought you were making some other point, but as it was more than five minutes ago, I don't remember. :-)
jverda at 2007-7-20 21:54:05 > top of Java-index,Java Essentials,New To Java...
# 16

> > Yeah, but it's still impossible to have deadlock.

>

> I know.

>

> I think I thought you were making some other point,

> but as it was more than five minutes ago, I don't

> remember. :-)

That's okay, I don't even remember what the point of the discussion was. Oh yeah, when do you need more than one lock. Well that's already been show so wtf am I doing replying?

kablaira at 2007-7-20 21:54:05 > top of Java-index,Java Essentials,New To Java...