• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Clarification on Synchronization.. say that three times fast

 
Jason Boutwell
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok. Home stretch.
I've implemented a global Lock Manager, and each ConnectionImpl holds a reference to it. It contains a HashMap with key = 'recNum', value='connImpl ref'. Each connImpl has a lock(int) method that simply forward to a lock(this, int) method in the lockMan (same with unlock).
My question is:
Does it suffice for thread-safety to synchronize the lock() and unlock() methods of the lockMan, rather than using synchronize on blocks of code within them, as many posters have done?
Should the lockMan itself be synchronized? Some have suggested that.
I am tempted to just add the keyword to the lock methods, which should block any calls until the thread completes, but wouldn't that also block another client from locking another record? Shouldn't concurrent locking of different records be allowed, or could this potentially corrupt the database if two clients try to modify different records at once? Wouldn't the synchronization of the writeRecord() method stop that?
So much synchronization, so little time.....
Thanks in advance!
 
Sai Prasad
Ranch Hand
Posts: 560
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to synchronize the code in lock method in LockManager where you access the local HashSet. Also you don't want to synchronize the code in the LockManager where you call the methods in Data. This will allow simultaneous locking of different records by different clients.
 
Jason Boutwell
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You need to synchronize the code in lock method in LockManager where you access the local HashSet. Also you don't want to synchronize the code in the LockManager where you call the methods in Data. This will allow simultaneous locking of different records by different clients.

Do you mean the HashSet contained within LockManager? But there is a 1:1 relationship between the HashSet(Map) and the LockMan. Why would I need to control that access from within LockMan?
Also, there is no reference in my LockMan to Data. The Data reference, like the LockMan reference, is contained in the ConnImpl.
My ConnectionImpl lock() method simply delegates to the LockManager:

and then the connectionImpl's modify method calls its lock() (args left out)

My question is: Should the syn keyword be on LockMan's lock() method, inside LockMan's code block, on ConnImpl's lock() method, or inside ConnImpl's lock() code block? Does it matter?
Thanks in advance!
On a similar subject, here is an interesting article on threading and the singleton pattern, posted recently on developerworks.
 
Daniel Brugger
Greenhorn
Posts: 5
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jason
My question is: Should the syn keyword be on LockMan's lock() method,
yes, I think it's the best place
inside LockMan's code block,
you could, but what would it help?
on ConnImpl's lock() method,
no, you were locking on the wrong object
or inside ConnImpl's lock() code block?
you could but I wouldn't suggest that
Does it matter?
yes, it does!
Hth.
Daniel
 
Jason Boutwell
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks guys.
I've added synchronized to the method declarations of lock() and unlock() in LockMan. Since I don't manipulate any other resource but the LockMan's HashMap, then there should be no conflicts.
I guess that I just needed to get it straight in my head. I don't often use the syn keyword around blocks of code or objects.
 
Sai Prasad
Ranch Hand
Posts: 560
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Assuming that you have only one LockManager instance and it contains the Hashset inside, you definitely want to synchronize the code in the lock method in LockManager. Also you don't want to synchronize the call to any sync methods in Data from the LockManager.
 
Jason Boutwell
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Assuming that you have only one LockManager instance and it contains the Hashset inside, you definitely want to synchronize the code in the lock method in LockManager. Also you don't want to synchronize the call to any sync methods in Data from the LockManager.

Why? What is the difference between synchronizing the method and synchronizing the code inside the method?
My LockManager contains no calls to Data.
 
Sai Prasad
Ranch Hand
Posts: 560
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jason:
Got it. I didn't read your first posting properly. In my submission, LockMan forwards the call to DataImpl.
Anyway, you need to think about threads trying to acquire the lock of DataImpl and LockMan. Think about the scenario:
1) Thread1(client1), got the lock for the LockMan and updates the HashSet to lock record 10. Now your HashSet has the key 10 and the value ConnImpl instance. Now Thread1 got the lock for the DataImpl and still wading through the lock() method in DataImpl
2) Thread2(client2) now tries to lock the record 10. In your current design, Thread2 can acquire the lock for LockMan and updates the HashSet with key as 10 and a different instance of ConnImpl as the value. You don't want this to happen.
You have some options. You need to implement wait(), notifyAll() in LockMan/DataImpl or create an ArrayList instead of HashSet in LockMan. That way, you will not overwrite the previous value while multiple threads try to lock the same record. I will go with the second option and wait/notifyAll in DataImpl.
This is one of the difficult areas in this assignment. You will get it.
[ June 12, 2002: Message edited by: Sai Prasad ]
 
Jason Boutwell
Ranch Hand
Posts: 40
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

In your current design, Thread2 can acquire the lock for LockMan and updates the HashSet with key as 10 and a different instance of ConnImpl as the value. You don't want this to happen.

I don't think that I will have that problem. Here is a portion of my LockMan's synchronized lock() method:

If Client 2 tried to access a record already put in the locks hash by Client 1, he would have to wait until the lock was removed.
Client 1 calls unlock, removes the lock from the HashMap, and notifies.
This seems to work, but I have yet to stress test it.
 
Sai Prasad
Ranch Hand
Posts: 560
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It looks fine. I didn't know you had implemented wait() in the LockManager.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic