• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Singleton Data class - locking on the locked records map

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi guys,

I'm pretty sure this topic has been covered before but I can't quite find how to solve it. If someone could help me (or point me towards another relevant thread) it would be great. My project is URLyBird 1.2.2.

Basically I am using the Singleton Data class with all synhronized methods. Behind this I am using a package level RoomDataController class that does the work (facade). This class controls the access to the DB (using another helper class), the caching of records on startup and writing the cache back to the DB on shutdown.

My problem is that as I am using all synchronized methods once lock() has been called on a record that is already locked the running thread will never be notified of the lock being released at it is the only thread allowed to run (I hope this makes sense).

So, within my RoomDataController I have a static map containing locked records. The lock method populates this. When this method is called again it will wait() as the record is locked. However unlock() can never be called because of the synchronization of all methods.

Again, apologies if this has been discussed before, but I couldn't find a (completely) relevant thread. Also, has anyone any thoughts on the design - using a singleton with a facade and a cache?

Thanks.
 
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Alan,

Are you familiar with how wait / notify / notifyAll work? From your question I would guess you are not. Maybe you should familiarize yourself with these methods, how they work and interact, what happens when you invoke one of them,... if you do, your question will solve itself. Good starting points would be the Object class and Oracle's Concurrency tutorial.

Kind regards,
Roel
 
Rancher
Posts: 175
Clojure Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In addition, the book Java Threads-- old but very good-- may be had in used condition for pocket change.
 
Bartender
Posts: 2418
13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Alan.
I am not sure if I understand your question.
Yes. You can synchronize all the methods in data class as suggested by Roberto. In this forum, download Roberto Perillo's paper about passing this exam.

The lock method does locking a record when one thread is making a room reservation. When this thread locks this room, it updates the room reservation record. After that, this thread unlocks the room.
Lock and unlock will prevent two threads making the same room reservation.

Hint :
lock (){
while (isLocked(roomNumber)){

try{
room.wait(); // wait for this room object
}
catch (...){ ...}
}

}

unlock(){
try{
room.notifyAll(); // notify all threads which are waiting for this room
}
catch (...){....}
}

This is a suggestion, in the GUI, once you hit the "reserve" button, you call the reserve() method. The reserve method implements these lock() ; update(); unlock (); once you hit the button.
You can create a few threads that try to call the the reserve method and see if you run into deadlock or run the update() method at the same time.

You can read Apress's SCJD study guide from Andrew Monkhouse and Terry Camerleno and read Robert Perillo's test class.

 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Himai Minh wrote:Lock and unlock will prevent two threads making the same room reservation.


That's not completely true. To prevent same room reservation you need extra business logic when booking a room. Lock and unlock methods prevents threads overwriting each other's data.
 
alan dunne
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Roel,

Thanks for your reply. I'm aware of the wait() notify() and notifyAll() methods. My problem is that once the lock() method is called by the second thread (in an attempt to lock a record already locked by the first thread) the wait() method is called from inside the synchronized(lockedRecordsMap){} block. That's fine.

However, as the methods in my Data class are all synchronized the update() and lock() methods cannot be called by the thread which owns the lock as the second thread is within the lock() method still and this must complete before another method can be called.

I have debugged this several times and I get deadlock in this situation.

Again, any help would be appreciated.

 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
From the javadoc of the wait()-method:

The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method.



So when a thread has to wait, it releases the lock (object's monitor). I don't get why the other thread could not acquire the lock and perform update and unlock. So if it's deadlocking there's definitely another issue.
 
alan dunne
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Well it releases the lock on the lockedRecordsMap, but as I am calling:

lock()
update()
unlock()

the first thread cannot call update() as the second thread is waiting in the lock() (synchronized) method, which owns the lock on the Data instance.

The first thread cannot access this instance as wait() only releases the (static) lockedRecordsMap, not the Data instance...

As the three methods are synchronized on the Data instance, i really should not have to synchronize on the lockedRecordsMap as well. But then how do I notify the second thread that the record has been unlcoked() as notify must be called from a synchronized block?

Thanks for your help.
 
Himai Minh
Bartender
Posts: 2418
13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Maybe, provide us your psuedo code and see why you have a deadlock. Are you sure you are locking on the same object? I guess your 1st thread locks on an object a , but 2nd thread wait for another object ,b. 1st thread notifies all other threads which waits for its object,a . 2nd thread waits for b forever.


1. First thread locks on a single object
2. Second thread waits for this object while this object is locked.
3. First thread updates this single object.
4. Second thread is notified and won't wait.

Deadlock may happens if you have this:
synchronize (a) {
synchronize (b){
....
}
}
and
synchronized (b){
synchronized(a){
....
}

}
 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

alan dunne wrote:As the three methods are synchronized on the Data instance, i really should not have to synchronize on the lockedRecordsMap as well. But then how do I notify the second thread that the record has been unlcoked() as notify must be called from a synchronized block?


You have a singleton Data class with all synchronized methods and you worry that you can't call notify from a synchronized block

Let's take a look at the following 2 code snippets




These are semantically equivalent! So if you use a synchronized method, you have a synchronized block to call wait/notify/notifyAll from. Synchronizing on 2 different objects (this & lockedRecordsMap) can be very dangerous and result in deadlock situations. Use it only when necessary (in this scenario it's NOT) and with great care.

Good luck!
 
alan dunne
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the help Roel and Himai.

I think I've got it working. After I call the constructor of my RoomDataController class (from my Data.getInstance(dbLocation) method) I then pass the Data instance to the RoomDataController. I then wait() on this instance in the lock() and call notify() on this instance in the unlock().

Does this sound ok to you? Also, have you any thoughts on the way I have set up my overall design?

Thanks again, Alan.
 
Roel De Nijs
Sheriff
Posts: 11604
178
Hibernate jQuery Eclipse IDE Spring MySQL Database AngularJS Tomcat Server Chrome Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Maybe you should have a look at the difference between notify and notifyAll...
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic