I have a question about synchronized block and ReentrantReadWriteLock. In the source code of book SCJD Exam with J2SE 5, I saw the following code
You can see that there is a ReentrantReadWriteLock write lock at outer side, and a synchronized (database) block inside the ReentrantReadWriteLock lock,
what is happening here? Is it ok to have a synchronized block inside the reentrantreadwritelock? I have search google but without any discovery. Why not all use reentrantreadwritelock instead using it and synchronized both? What is the reason behind?
In the code snippet you presented you are acquiring 2 different locks.
The first is the write lock of a Read/Writer lock that it's been used to state you are going to write.
The second one is the lock of the database object when you are using the synchronized keyword, because since you only
have a single RandomAccessFile database object, yo don't want anybody else changing the current pointer where to read/write in the file when you call seek().
Google sometimes provides too much information you need to sift through.
The first place to look at is the Java API for ReentrantReadWriteLock.
The Java API is your friend.
ReentrantReadWriteLock was introduced with the java.util.concurrent APIs in Java 5.
If you want to find out more about it check this excellent book by one of the major sponsors and proponents of java.util.concurrent.
Your information is useful. But I am still wondering, is it necessary to have two locks in this code snippet. By my understanding, synchronized locking will lock the object it defines until the code inside the synchronized block is run over to prevent other threads' concurrent modifying. For ReentrantReadWriteLock, which substitutes synchronized block, what I know is it will block other thread to enter the code in the try block between lock and unlock for write action in this case.
So could we just use one lock method, synchronized block or ReentrantReadWriteLock, in this code snippet rather than use two lock methods. What our purpose is to protect the database variable, seek and write method. Could you please give some advices about that.
Thanks and best regards
posted 10 years ago
A little bit understand the question. The first "recordNumbersLock" is used to lock the non thread safe "recordNumbers" hashmap object. The second synchronized lock is used to locked the "database" RandomAccessFile object.
The only job of the "recordNumbersLock" is to protect the recordNumbers-Hashmap from concurrent access. Every access to this object should be done over this lock. That has nothing to do with access to the RandomAccessFile "database". It should be protected too, which happens by sorrounding it with a synchronized block.
There are many ways to fullfill the requirement to program a thread-safe application. One way to make a method (that writes data to what object ever) thread-safe is to mark the hole method as synchronized.
Another way can be to synchronize as less code as possible by using locks and synchronized-blocks very sparely and carefully. And only there where it is needed. No code that does not need to be protected from concurrent access should be protected. I think this was the approach of the sample application in the book. Your are free in your choice if you use synchronized or locks, it depends on how much you are familiar with them. So, the code sample in the book represents the choice of the author.
BTW if you're programming close to the book you should be aware of the persistDvd() method which seems not to be thread-safe as you can see here Thread-1 and here Thread-2. While the removeDvd() method is thread-safe, the persistDvd() is probably not. Solutions are mentioned here Thread-3
PS. Perhaps we should invite Roel here, i'm not sure but i think he marked every method in his Data class as synchronized... Roel, did you?
Bernd Wollny wrote:PS. Perhaps we should invite Roel here, i'm not sure but i think he marked every method in his Data class as synchronized... Roel, did you?
That is indeed exactly what I did The singleton design pattern applied to the Data class with every (public) method marked as synchronized is the easiest possible approach (in my humble opinion). And because I wanted to keep things as easy as possible it was obvious I took this road (highway) to becoming a SCJD