Forums Register Login

Create/Update Method Synchronization

+Pie Number of slices to send: Send
Hi,

I would like to know different opinions on Synchronization of Create/Update method:

1. Synchronize Entire method?
2. ReadWriteLock on recordNumbers -
a. If the option is create add the recordNumber and location(append at the end) to the collection and release the lock.
b. Synchronize on raf and write to file?

My concern with option 2 is - what if there is a read/write between 2a and 2b.

Please let me know your thoughts on this.

Thank You,
Vijay
+Pie Number of slices to send: Send
Hi Vijay,

I went for the first option: synchronize all methods (so not only create and update). of course your data class should certainly be a singleton, otherwise it will not have any effect.
The drawback of this approach is that your program is not that concurrent/performant as it could be. But your code is very simple, clear and can easily be understood by a junior programmer.

The second option is similar to how it is described in the Andrew Monkhouse book. And i think the main concern there is what if 2 client will create a new record.
client1: determine offset, offset = database.length
client2: determine offset, offset = database.length
client2: write record at end of file
client1: write record at end of file (and so overwrite the record written by client2)

a read or an update or a delete in between (offset determination and the actual write) would have no effect in my opinion, because the records are fixed size, so updating or deleting a record will result in same size.

I don't have any idea about how to solve this item and i looked to sources of Andrew's book and there can just happen the same i guess.

Kind regards,
Roel
+Pie Number of slices to send: Send
Thanks Roel for your detailed explanation. I think Synchronizing entire method may impact some performance but that seem to be the simpler approach.

I wonder how many people used the 2nd option!? and how they implemented it? hope someone answers it, I'm curious to know.

Thank you,
Vijay
+Pie Number of slices to send: Send
I'm going with little different approach:

1. Data-class has one ReentrantLock, which controls access to lock-hashmap containing locked record numbers
-> Methods are NOT synchronized (you should do this in any case - no matter what's your approach)
2. Every client should instantiate Data-class
3. Every client get's own access to file - that is, RandomAccessFile is opened every time
4. I'm using WRITE_LOCK = -1, to inform, that writing is forbidden while using find method

-> Gives real concurrent access to file
-> Already tried with Cache-implementation - too compilcated -> changed whole back end.
-> UB 1.3.3 does not define lock cookie -> RMI Factory Design pattern is a must, since RMI does not guarantee single thread access to server from client.
+Pie Number of slices to send: Send
 

Jari Timonen wrote:
UB 1.3.3 does not define lock cookie -> RMI Factory Design pattern is a must, since RMI does not guarantee single thread access to server from client.



UB 1.3.1 also defines no lockCookie, but i didn't use the RMI factory design pattern. so it is not a must
+Pie Number of slices to send: Send
 

Roel De Nijs wrote:

Jari Timonen wrote:
UB 1.3.3 does not define lock cookie -> RMI Factory Design pattern is a must, since RMI does not guarantee single thread access to server from client.



UB 1.3.1 also defines no lockCookie, but i didn't use the RMI factory design pattern. so it is not a must



Ok. Maybe i'm just too accurate ;) But... there is then possibility, that thread that locks record and after that reads it, is different.
+Pie Number of slices to send: Send
 

Vijay Sai wrote:Thanks Roel for your detailed explanation. I think Synchronizing entire method may impact some performance but that seem to be the simpler approach.

I wonder how many people used the 2nd option!? and how they implemented it? hope someone answers it, I'm curious to know.

Thank you,
Vijay


Hi,

I like your idea about locking whole methods, did you used it in your assignment and did you passed?

Regards,
Adam.
+Pie Number of slices to send: Send

Hi Adam,

I thought of exploring the 2nd option to learn more but didn't get a chance to implement it. I'll be restarting it soon. For the first option, you can implement it as Roel mentioned above.

Thanks,
Vijay
+Pie Number of slices to send: Send
 

Jari Timonen wrote:

Roel De Nijs wrote:

Jari Timonen wrote:
UB 1.3.3 does not define lock cookie -> RMI Factory Design pattern is a must, since RMI does not guarantee single thread access to server from client.



UB 1.3.1 also defines no lockCookie, but i didn't use the RMI factory design pattern. so it is not a must



Ok. Maybe i'm just too accurate ;) But... there is then possibility, that thread that locks record and after that reads it, is different.


There are several ways that you can ensure that the client who locked the record is the client who is modifying the record without using a factory, although I personally think the factory method is the most elegant.

The lock method you expose via RMI does not use the same signature as the lock method defined in the Sun interface. Given that, you could easily justify modifying your RMI methods even further - say by creating your own lock cookie or some other "id" field. When the client calls the remote method with that ID field set, you could use it to set the name of the thread that is currently running for that particular client which can then be used within the Data class' methods.

Or there is the option that I believe is against the intent of the assignment (but you will not be marked down for doing this) - only expose business methods to the client. If you only expose a book() method, and that book method internally calls lock(), update(), unlock() then you will be assured that the same thread is calling all three methods. Makes a mockery of having cookies (for those who have cookies).

Note that although I have said that I prefer the factory solution, and although I believe that only exposing business methods is going against the intent of the assignment, I am also explicitly stating that this is pure hubris on my part: the reality is that this assignment (as with most assignments you will get in real life) was written by someone else, and any attempt to state that "this is what they intended" based on just a reading of the provided document is bad mind reading at best. In a real life situation you would be better off going to the author of the document and saying "here are 'x' number of possible ways of handling this problem - which do you prefer. You might then find that they never considered the problem you've found, and/or that they think that solution 'y' is better than anything that they had previously thought of. Meh.
+Pie Number of slices to send: Send
Thanks Andrew. I already hide my lock/unlock methods from RMI. Exposed only business methods. I'm using thread id as locking cookie inside Data-class
+Pie Number of slices to send: Send
 

Jari Timonen wrote:Thanks Andrew. I already hide my lock/unlock methods from RMI. Exposed only business methods. I'm using thread id as locking cookie inside Data-class



Sounds too simple to me, but maybe I am worried for nothing so to be sure you don't make mistake in the rmi part.

If you have an interface with a lockCookie you should use that one to make sure the right client locks/updates/unlocks the record. If you don't have a lockCookie in your interface, you should be aware that RMI doesnot guarantee that consecutive requests from 1 client are handled by the same thread.

Kind regards,
Roel
+Pie Number of slices to send: Send
 

Roel De Nijs wrote:

Jari Timonen wrote:Thanks Andrew. I already hide my lock/unlock methods from RMI. Exposed only business methods. I'm using thread id as locking cookie inside Data-class



Sounds too simple to me, but maybe I am worried for nothing so to be sure you don't make mistake in the rmi part.

If you have an interface with a lockCookie you should use that one to make sure the right client locks/updates/unlocks the record. If you don't have a lockCookie in your interface, you should be aware that RMI doesnot guarantee that consecutive requests from 1 client are handled by the same thread.

Kind regards,
Roel




I'm aware of those. There's no locking cookie in my interface. As I said before, factory design + thin client is a must OR andews "set thread name" strategy.

-jari
+Pie Number of slices to send: Send
Hi Roel and Jari,

Please let me know your thughts on this:

1.get writelock
2. In the try /catch block - synchronize(RAF) and write to the db.
3. unlock in the finally block


Thanks,
Vijay
+Pie Number of slices to send: Send
Hi Vijay,

Vijay Sai wrote:
1.get writelock
2. In the try /catch block - synchronize(RAF) and write to the db.
3. unlock in the finally block


don't know what you mean with "3. unlock"? If you mean a call to the unlock-method from within the update/delete method, I don't think that's a good idea. These methods should just do what they are supposed to do, and that's updating/deleting, not locking/unlocking the record. This should be seperate calls.

Without the use of a lockCookie to update a record it would look like this


in the update-method you would have something like:

So the seek and the write should always be 1 atomic operation, otherwise you could corrupt your data file.

Kind regards,
Roel
+Pie Number of slices to send: Send
Hi Ranchers,

I have a threading question that arose while I was implementing lockRecord and unlock() for B&S 2.2.1...

According to page 35 of Core Java 2, Vol. II (7th ed.) by Horstmann, Cornell, the following are equivalent...

public synchronized void method() { //method body... }

public void method() {
implicitLock.lock();
try
{ //method body } finally {implicitLock.unlock();}

In this spirit, I thought I'd try to code simply in my locking methods as follows (somewhat in pseudocode)...

class LockManager {

private static Map<Long, Long> cookieMap =
new HashMap<Long, Long>();

public synchronize void lock(long recNo, long cookie) {

while(cookieMap.containsKey(recNo))
wait();

long cookie = randomCookieGenerator.nextLong();
cookieMap.put(recNo, cookie);
return cookie;

} // end lock


public synchronized void unlock(long recNo, long cookie) throws SecurityException {

if(!cookieAndRecordMatch(recNo, cookie)) {
throw new SecurityException();
}

cookieMap.remove(recNo);
notifyAll();

} // end unlock

} // end class

Puzzlingly to me, this seems to deadlock, i.e., some threads stay blocked waiting in lockRecord forever. Why?

Thanks,

Grary

+Pie Number of slices to send: Send
Hi Grary,

Could you edit your previous post and put your code blocks in code-tags, it keeps the identation intact and so makes your code snippets a lot more readible

Regards,
Roel
+Pie Number of slices to send: Send
Hi Roel,

The sequence should be same as you mentioned- lock, cretae/update/delete, unlock. I was talking about WriteLock.unlock() in the update/create method.

Thanks,
Vijay
Do not meddle in the affairs of dragons - for you are crunchy and good with ketchup. Crunchy tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com


reply
reply
This thread has been viewed 2405 times.
Similar Threads
Locking Schemes: Tactical View 01
Design 01
B&S: Locking
Denny's DVD setDatabaseLocked method
NX Problem with Threads and Concurrent Access to Database
More...

All times above are in ranch (not your local) time.
The current ranch time is
Mar 28, 2024 16:03:43.