Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

URLyBird 1.3.1: Locking Problem

 
Leo Ho
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi folks, I'm doing locking on the server-side (e.g having a biz layer with methods such as book(), search() etc.) and stuck with the following situation:

- Thread A gets lock for Record 1 -> OK
- Thread B gets lock for Record 2 -> OK
- Thread C gets lock for Record 1 -> fail, wait()
- Thread D gets lock for Record 2 -> fail, wait()
- Thread A finishes record 1 and notifyAll() -> the scheduler chooses Thread D to run, but Thread D still cannot lock record 2, thus wait() (so we still have C, D in the waiting queue)
- Thread B finishes record 2 and notifyAll() -> the scheduler chooses Thread C to run, similarly Thread C still cannot lock record 1, thus wait()

-> Thread C, D wait forever.

How you guys handle this situation???

In addition, by reading through many posts, can s/o comfirm me the following: if I do server-side locking (e.g. book() which calls lock(), read(), delete(), unlock() respectively) then I don't have to be worried about WeakHashMap or Unreferenced since there won't be any case that unlock() cannot be called, is that right?

Many thanks,

Leo
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thread A finishes record 1 and notifyAll() -> the scheduler chooses Thread D to run,


Huh? Thread A notifies all threads waiting on record 1, not record 2. So Thread D will not be woken, but thread C will.
 
Leo Ho
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Barry Gaunt:


Huh? Thread A notifies all threads waiting on record 1, not record 2. So Thread D will not be woken, but thread C will.


How can you do that??? My current implementation is using one lock for all the record locks, thus when you call lock.notifyAll(), you don't know which threads will get notified -> my situation. Can you add details to your solution?

Leo
 
B Chen
Ranch Hand
Posts: 89
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I thought that when you use notifyAll(), all threads waiting on the object will wake up? So both thread C and D should have woken. But only one of them will be able to continue working. The other one will go back to waiting.
If you called notify(), then the scheduler will choose one waiting thread to wake up. And it may choose the "wrong" thread because the record it is waiting for has not been released.
[ April 12, 2006: Message edited by: B Chen ]
 
Leo Ho
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by B Chen:
I thought that when you use notifyAll(), all threads waiting on the object will wake up? So both thread C and D should have woken. But only one of them will be able to continue working. The other one will go back to waiting.


Nope, notifyAll() do wake up all threads, but they will then compete to get the lock and only one of them can get execute - otherwise you will have multiple threads in your critical section.

Leo
 
Barry Gaunt
Ranch Hand
Posts: 7729
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My current implementation is using one lock for all the record locks


You did not write that in your original post. If it's so how do you have:

Thread A gets lock for Record 1 -> OK
Thread B gets lock for Record 2 -> OK


holding the lock at the same time?
 
B Chen
Ranch Hand
Posts: 89
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Leo Ho:


Nope, notifyAll() do wake up all threads, but they will then compete to get the lock and only one of them can get execute - otherwise you will have multiple threads in your critical section.

Leo


All the waiting threads wakened by notifyAll will, in turn, execute the code in the critical section. For example:

Thread A acquires mutex
Thread B, finding the mutex already lock, waits
Thread C, finding the mutex already lock, waits
Thread A finishes its work, does notifyAll(), and releases mutex
Thread B and C both wake up and compete for mutex
Thread C acquires mutex, does its work, and releases
Thread B acquires mutex, does its work, and releases

It could be that thread B acquires the lock first. But the point is, the second thread will acquire the monitor after the first thread is done.
[ April 12, 2006: Message edited by: B Chen ]
 
Leo Ho
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh man, I just got screwed up about threading. I thought that even if all threads get notifyAll(), only one of them will acquire the lock and run while the others continue living in the wait state - which is of course very wrong.

Thanks Chen, you're exactly right.

Leo
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic