• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Lock/Unlock - same thread?

 
Jason Then
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi yall,

Just wondering, does the Thread which locks a particular record need to be the same Thread which then unlocks that record?

After running Alecsandru Cocarla's Data Test, I found that my Data class throws an IllegalMonitorStateException because of this reason - i.e. a different Thread which knows the lock cookie value is unlocking the record.
My class passes Roberto Perillo's Data Test, however

So am I incorrect in this assumption that the same Thread which locks a record, needs to be the same Thread which unlocks that record?
It seems to me that there would be significant work in implementing a locking mechanism which allows any other Thread to unlock that record.

(Edit: Ok so I've now realized that there isn't *significant* work in implementing this locking mechanism.
Previously I was just delegating to a Reentrant lock, but to allow a different Thread to unlock a record you can just use the wait(), notify() paradigm.
Delegation to a Reentrant lock is still nicer in my opinion.
I am also considering the possibility of using a ReadWriteLock to implement 2-phase record-level locking, which would require that the same Thread which locks a record, unlocks it.)

Cheers,
Jason

 
Jim Hoglund
Ranch Hand
Posts: 525
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Jason and welcome to JavaRanch. I think of locking as "taking" or "securing" an object's
lock with the "synchronized" key word and then releasing it when the synchronized code block
completes. The only other way to release an object lock is to call wait() within the synchronized
block. This will: 1) block the current thread, 2) release the object lock for other threads to use,
and 3) queue up the current thread to regain the lock when object.notify() is called later.

Jim ... ...
 
Roberto Perillo
Bartender
Posts: 2271
3
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Howdy, Jason!

Jason Then wrote:Just wondering, does the Thread which locks a particular record need to be the same Thread which then unlocks that record?


Hum... not necessarily. On the client side, it will end up being the same, since theoretically there's only one Thread locking/updating/unlocking, so you can, for instance, use the Thread's ID to identify the client. But, on the server side, it will depend on the way you implement your locking mechanism. If you call lock/update/unlock from the client side, then, on the server side, the Thread that locks a record may be different from the Thread that locks it (in this case, you'll have a thick client, beucase all the logic will be implemented on the client side). But if you have a method, like bookRoom() that you call from the client side, and this method calls lock/update/unlock, then the Thread that locks the record will be the same that will unlock it (in this case, you'll have a thin client).
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A record must be unlocked with the same lockCookie as the one generated when locking this record.

If you don't have an interface with a lockCookie (like the interface I had to implement) you had to come up with a way to identify the different clients. I used some kind of clientId. But the same logic applies: a record can NOT be unlocked with another clientId as the one used to lock this record.

The locking and unlocking of a record can be done by the same thread, but it also can be done by another thread when using RMI. Remember RMI does NOT guarantee that consecutive calls of the same client are handled by the same thread (so using the thread to identify the client is not a good idea).
 
Raf Szczypiorski
Ranch Hand
Posts: 383
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just a question - what does your locking scheme look like? Do you preserve a ReentrantLock for every record? I would assume that. Otherwise, if you have only one ReentrantLock and unlocking throws IllegalMonitorStateExc, it means that locking a single record keeps the whole database in a locked state, and it waits for someone to unlock it? Then I would say it has very weak performance.
Please write a little more about your locking solution.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Raf,

My locking mechanism doesn't use the fancy new conurrency API, but the old-school wait/notifyAll used in synchronized blocks. And I have a map to keep track of the locked records. So an unlocked record can be locked by any thread (client) if that thread (client) does not hold already another locked record (and the record is simply added to the map with the client identification). And when a locked record is unlocked (can only be done with a thread that has the corresponding client identification), the entry is simply deleted from the map (and all waiting threads are notified).

Hope it helps!
Kind regards,
Roel
 
Raf Szczypiorski
Ranch Hand
Posts: 383
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Roel,

thanks for the information. But I wasn't asking about your locking strategy, but the author's My assignment is long sent, and this Thursday it is going to be full 6 weeks and I will most likely have to resend (Oracle and this whole process is ridiculous. I would even say that they moved the seriousness of this certificate by 10 levels down - in my own eyes, this is nothing more than a cert that nobody in Oracle cares about, which is a pity as it is really not that common and rather involved).

If the author asks a question about locking, to b able to answer it (and not say "maybe this, maybe that" :>) we need to understand what he does.

Raf
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If a real question is asked about the author's locking mechanism (which we can't answer), he always can answer it himself (as he visits this forum still regularly). I don't have the book anymore, because it was bought by my previous company.

And don't forget that the locking mechanism from the book contains a violation of a must requirement (which is intended, so a user can't just copy-and-paste the locking mechanism).
 
Raf Szczypiorski
Ranch Hand
Posts: 383
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why did you think I was asking you about his locking mechanism, Roel? Which book are you referring to, Andy's? I didn't mention it anywhere?
 
Jason Then
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Raf - yes I am using a ReadWriteLock per Record.

But given the results of this discussion I might change the locking mechanism to wait on a dedicated object instead - so that I don't get that pesky IllegalMonitorStateException when another Thread tries to unlock it.

Locking a single record doesn't lock the whole database - what would be the point in that? Threads are synchronized on individual records, rather than on the Data object, so don't worry. I will figure something out

I agree though, it is unfortunate that this certification has been undervalued by Oracle. And it really sucks that they don't give you a numeric score - just a pass/fail grade
 
Roberto Perillo
Bartender
Posts: 2271
3
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok champions, I think there's misunderstanding here, and I think I know where it is.

Raf Szczypiorski wrote:Why did you think I was asking you about his locking mechanism, Roel?


Because of this statement:

Raf Szczypiorski wrote:But I wasn't asking about your locking strategy, but the author's


I think Roel understood that you (Raf) were talking about Andrew's book. But when you asked:

Raf Szczypiorski wrote:Just a question - what does your locking scheme look like?


You (Raf) were asking to the author of this thread, right?
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Raf Szczypiorski wrote:Why did you think I was asking you about his locking mechanism, Roel? Which book are you referring to, Andy's? I didn't mention it anywhere?


My mistake! You were referring to the locking mechanism of the original poster I saw "author" and I directly thought about the author of the SCJD book (which a lot of SCJD'ers have used to achieve their success), Andrew Monkhouse. I'm just back from 1 week holiday, so apparently I'm still a bit in holiday-mode
 
Raf Szczypiorski
Ranch Hand
Posts: 383
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roberto and Roel - no problem, no worries, it was just a little funny :d but truth be served, I wasn't overly specific about who I was referring to. Peace

@Jason - so this is the problem - you have a lock per record, which requires the same thread to unlock the record as locked it. The data test by one of the forum mods (sorry guys, can't remember whose!) uses always the same thread to lock and unlock, that's why it works.
If you use RMI, you will be in big trouble with this approach, as you have completely no control over which thread locks and unlocks. It may happen that for a few roundtrips it will work, but then suddenly it will fail - there are no provisions made by RMI. You could for example make a single locking queue on the server and it would be the single thread that locks / unlocks.
My approach was similar to Roel's, with a single lock per database and a map that associated record numbers to locks, and each call to lock / unlock would acquire and release the database's lock, that's why there are no IllegalMonitorStates.
Are you sure (as you write in the first post) that changing ReentrantLock to Java primitives will change anything? You will still have different threads locking and unlocking the records?
 
Jason Then
Greenhorn
Posts: 17
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Raf - yes it changes the behaviour, so it's all good

I have opted away from using a Map to store locks for records.
Instead, I use a List of the actual records and the records themselves are lockable.

I also cache deleted record numbers in a Queue for O(1) creation which reuses deleted records.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic