Hi Biang,
Hopefully you have already thought about your own tests (and are going to post them as well so others can see them). Here's some of my thoughts:
The best thing you can do is a proper code review. The problem is that you need objective observers - most people spot few bugs when they do a code review of their own code. But try and walk through your code, trying to imagine what will happen if two threads run the given bit of code simultaneously. If there is a potential for a problem, no matter how remote, you need to fix it.
On the more practical side ....
One thing you can try to do is to stress the server: create 10 threads all of which try to gain a lock on the same record at the same time. This means that you will have to do all the
thread initialization first, then get them all to wait() on a common object. When they have all completed initialization, notifyAll() of them so that they all try to get the same lock at the same time. Whoever gets the lock should sleep() for a second then release the lock. All with suitable System.out.println() statements so you can see whether this is working. If it is working, then only one of your threads will get the lock, and the rest will have to wait. When the successful thread releases its lock another thread will gain the lock and so on. You need to see the evidence of this in your output.
Then, a similar concept: have several threads all trying to do something at the same time (not necessarily on the same record). One test I did was to have one thread per record in the database, and have each thread overwrite it's equivalent record with a
string containing the record number. (So thread 5 overwrote record 5 with the String[] {"5","5","5"....}). Again - try to have all the threads do this simultaneously. At the end of the run, print out every record in the database. Does it contain the data you expect?
You can vary that test by changing the task. So have all the threads do creations for instance. Again, you want to do all the initialization up front, so pre-build the data you are going to create before going into your wait() state. Then when you wake up, you can just hit the server hard with all the data.
Another test could be to have multiple threads do different things simultaneously. So have one thread doing reads, one doing updates, one doing creates, one doing deletes. Say I have 20 records to start with. I could have 1 thread reading records 1 - 5, one thread modifying threads 6 - 10, one thread deleting records 11 - 15, and one thread adding records 21 - 25. Again, do all your initialization work up front so that you have the data ready to overwrite records 6 - 10, and all the data ready to create records 21 - 25 etc. (For the reads, just read them and store them in an array - dont process them while you are reading. When you have read 5 records, then you can print out what you read. Then verify that you did read the right records and got back the right data, that you did modify the right records, that you did delete the right records, and that your newly created records are where you expect them and contain the right data.
Regards, Andrew