• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Deadlock on the thin cleint

 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hallo,

I choose to hide the lock and unlock methods on the client side, that means my clients only search and book.In my client implemetation I do somethig like :



The logic is relativ simple, lock, process, unlock and if an exception ocures then throw an exception and release the record. Until here is ok BUT
if someone tries to implemets an other kind of client, where the same client can lock more records (and release them after in the same order) I have a problem, I have the clasic scenario :

Client A lock record 1
Client B lock record 2

Client A lock record 2
Client B lock record 1

Deadlock

I try a time out mechanism(solution 1) and then I try to force the client to lock only one record(solution 2).

Both are not specified in my specs. Both are working but I ca not decide which one to chose.

Comments and sugestions are welcomed.

Thanks,
Mihai
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's a good thread about Deadlocks & Stalelocks HERE

I don't like the idea of the timeout, because what to do in this case ?
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,

the "time out" feature : you can lock a record for a specified amount of time. If the record is not relaset until then will be relased and an exception raises.

Regards,
Mihai
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OK, so :

Client A lock record 1
Client B lock record 2

Client A lock record 2
Client B lock record 1
-> Time out, exception thrown, "timeout : Client A can't lock record 2"
Client A can't finish its transaction
Client B performs ...

But in this case :
Client A lock record 1
Client A lock record 2
Client A performs ...

So client A transaction result (error or not) may depend on the intervention of another client during the transaction... That's what I don't like.
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,

You're right, I aslo don't like this if the client is slappy and just try/catch/swallow the exceoption you can go realy in trouble. I must think on something how to prevent this before it happen.

Any tips ? How did you solve this problem ?

Thanks for "Dealing with Deadlock/State Locks".
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


I have not solved it yet

I think that allowing only 1 record-lock per client is a valuable and simple solution as we don't need to lock more than one record for the application. But on the other hand, I'm trying to make the database the most generic...
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok also thing that only one cleint lock is the most simple, in this case I still throw an exception if a cleint tries to lock more records (without lock them first) but in this case the exception raises before the lock -> no lock - no deadlock.

What you think ?

Regards,
Mihai.
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think it's better than the timeout solution.

With that, you avoid a deadlock scenario, but you add a constraint to the database.
The question I'm asking now is what is preferable between :
- to add some constraints to the database to avoid deadlocks
- to let the client of the database ensure a deadlock scenario will not occur.
 
Anton Golovin
Ranch Hand
Posts: 530
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
test
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,

Sorry for my late answer but I have a hard day today.
If I understand you the question is : Freedom for the user ? To be or not to be ?
To be onest before the user(client) breaks something I prefer to limits his activitiy field. To much freedom increases the complexity.
In my implemtation the LockManager is pluggable so if the current solution is not satify the requirenments in the future you just change it (with a new one) the LM the data layer( databse in your post) remains the same.



Regards,
Mihai
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Mihai,

I've found another interesting thread about deadlocks.
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,

ThanX fot the link, quite interesting. I think I already try both solutions : the "onyl one record at time" and the "lock order" (here you need individual looks).
The "only one record at time" seems to be the simplest - here I throw an exception a checked(or not) when a "bad" cleints tries to lock more records at once.
I also have a check method (isLook(int):boolean) but I not so happy about it. This method can be tricky - if you check a record state and you find it unlock - that means you can lock it without problems - and just in this moment an other thread(client) does the same stuff but is "faster" than you and he locks it before you - then exception, even if the checkMethod retuns true.
You don't have the same problems ?


Regards,
Mihai
[ October 27, 2005: Message edited by: Mihai Radulescu ]
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I also have a check method (isLook(int):boolean) but I not so happy about it. This method can be tricky - if you check a record state and you find it unlock - that means you can lock it without problems - and just in this moment an other thread(client) does the same stuff but is "faster" than you and he locks it before you - then exception, even if the checkMethod retuns true.
You don't have the same problems ?


If I understand your pb :

Client A calls isLock ->return false;
Client B calls isLock -> return false;
Client B locks the record
Client A locks the record


I don't have this problem because for each record, I've one object on which I synchronize my lock calls (and more !)

synchronized(aRecordObj) {
isLock? ;
lock ;
}
[ October 27, 2005: Message edited by: Seb Mathe ]
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,


I presume that you use that on your data(DBMain) class and this OK, in my case I choose to have a extra class for the lock manager. In the javadoc from the
lock manager I explain the isLock():boolean method risks and for usage I sugest sumethig similar with you example.

Am I right ?


Regards,
Mihai.
[ October 27, 2005: Message edited by: Mihai Radulescu ]
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And I think you just nest some synch blocks :

synchronized(aRecordObj) { -> first block
isLock? ;
lock ; -> second bloc
}

This can lead you to a deadlock.
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, I can't have a deadlock here because the lock operation I've used here is not synchronized.

I don't see why my example is not applicable to your LockManager, and why you throw an Exception in the case you've described.

Regarding the requirements, I think the normal flow for a client trying to lock a record should be somethink like :

while(recordIsLock) {
wait;
}
lockRecord;


So if such a block is not synchronized, your scenario may occur, and for me, it violates the requirements.

(Note that I don't see why Sun's isLocked method is exposed to the client except for testing purposes)
[ October 27, 2005: Message edited by: Seb Mathe ]
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,

Lets draw some lines :

Intro :
If I uderstand you have a lock non synchronized lock method (and maybe a syncronized one).You also have a "general" lock object (I presume static because it must be the same for all the cleints). Before you lcck you make your block atomic by synchronize it with this "general" lock.



No, I can't have a deadlock here because the lock operation I've used here is not synchronized


As I said I have a extern look manager(the clasic type, all threads are waiting on the same lock). All the methods in the lock manager(lock(int), unlock(int), close(), isClosed():boolean and isLocked():boolean) contain syncronized (on the "general" lock object) blocks.

That's why I thought that yout lock methods are syncronized also.



and why you throw an Exception in the case you've described.

A cleint can lock only one record at time, otherwise some exception raises.
In the my scenario first thread lock uses the isLocked(int):boolean method and it gets a false - at it tries to lock the record, but in the same time a other thread slides in and locks the same record, then the first thread gets an exception.



I don't see why my example is not applicable to your LockManager

I am not 100% that I understand your example.
You don't have/use the synchronized methods in yout lock manager but you synchronize all the usage on the Data class(a Singleton) using the same lock.
Am i right ?
If it is loke this, your LockManager class behavior is based on a "smart" usage and this is bot so good for a design (IMO).
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry, for sure, I don't get your design 100% .

Especially this point (I'm maybe too tired )


I also have a check method (isLook(int):boolean) but I not so happy about it. This method can be tricky - if you check a record state and you find it unlock - that means you can lock it without problems - and just in this moment an other thread(client) does the same stuff but is "faster" than you and he locks it before you - then exception, even if the checkMethod retuns true.


I will try now to give you more details on what I was thinking about :

My exemple applied to a LockManager, with the rule : 1 lock max per client.


So,


You don't have/use the synchronized methods in yout lock manager but you synchronize all the usage on the Data class(a Singleton) using the same lock.


Of course not : my "LockManager" uses synchronized calls using differents locks (1 per record).

I'm sure we will understand us shortly
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Seb,



Sorry, for sure, I don't get your design 100%.


My design is relative simple I have a LockManager with two implementation
1.The same lock for all the cleients
2.One lock per client.

Both are functional.At least I hope

The LockManager interface is relative simple, it contains lock(int), isLock(int):boolean, release(int), close() and isClosed():boolean.

Both are using the "one client lock one record at once".I also throw an exception if a client tries to .....

My problem was (and is still is) the isLock() method - and this is a general problem by all the test method. The isLock() is syncronized - but on usage an other thread can slide between test block and its execution block and that lead me to a race condition. To avoid this I need to syncronize the whole test block with the same lock that lock and release method operate (I think aRecordObj in your example) but the lock(s) are private memers and I don't like to make them visible.

This was one ideea : to make the locks visible.

by example :



the lock(recId) uses the same lock so I have no problem if the method lock(int) is called the lock will be released. Also the whole if statement is now atomic - no sliding threads. The lock if final so bad cleints can not
null it.

But I don't like the idea. If a bad user just gains the lock and never release it then ... I must think about it.

And now back to your solution.
You use an individual lock for each client (thread), but I don't understand is how you get the "aRecordObj" outsite of your lock manager ?
I use the same term like your example :

synchronized(aRecordObj) {
isLock? ;
lock ;
}
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Still have questions :

Why is your isLock() method synchronized ?



final Object lock = lockManager.getLockFor(int);
synchronized (lock) {
if(!lockManager.isLocked(recId)) {
//do stuff
lockManager.lock(recId);
}
}


Do you really use such code from outside the LockManager ? (And if so what would be the 'else' statement ?)



And now back to your solution.
You use an individual lock for each client (thread), but I don't understand is how you get the "aRecordObj" outsite of your lock manager ?
I use the same term like your example :


I don't need to get the "aRecordObj" outside the lock manager.
And I don't use en invidual lock for each client, but an individual lock for each record. (When I was saying "1 lock max per client" I wanted to say "one client locks one record at once")
 
Seb Mathe
Ranch Hand
Posts: 225
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If a bad user just gains the lock and never release it then ... I must think about it.


I think this is another thing.

We can talk about it after if you want...
 
Mihai Radulescu
Ranch Hand
Posts: 918
IntelliJ IDE Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,Se Idecide to treate the isLock problematic in to separat thread so if you can take a lock an the thread
"isLock(int):boolean method and the synchronized block"

Also you can take a look on the thread :
"Hi, I have passed my assignment" from Jesse Xie Y.S he(she) suggests that :

5. Make sure that the process of checking if a record is locked by other thread or checking if the record is exist, before locked a record, should be keep in synchronized block.


Thanks,

Mihai.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic