1. For our purposes, one "program" == one JVM invocation. Someone calls
java -jar runme.jar
(or something like that) and this starts a single JVM process on the machine. Within that process, there may be multiple threads, and multiple classes involved, any of which could be accessing the DB file (depending how you write the classes.) But they're all within the one JVM process. No other JVM process, nor any other non-JVM process, will be running at the same time and accessing the same DB file you are.
In server mode, there are also a bunch of other JVM processes on other machines - the clients. But they're not accessing the DB file; they're sending requests through a socket or something. The server responds to those requests. So again, only one program (the server) has direct access to the DB file.
2. Ummm, this can be long & involved, depending how you have things set up. But I would suggeest that whatever you're synchronizing on for the lock and unlock,
you should sync on the same object for update and delete, and maybe read. (The last is more arguable if you want to allow dirty reads for speed.) But for methods which require a cookie, the method needs to be able to check if the cookie it's given as a parameter matches the cookie that was assigned when the record was locked. That means that somewhere, you're storing the expected cookie value. This is mutable data which is
probably accessible by more than one
thread. (Especially if you're using RMI.) Even if those threads aren't concurrent, the fact that there are multiple threads means that synchronization is usually a good idea. The Java memory model allows different threads to cache their own copies of data, which means that different threads may be looking at different copies of data, and the different copies may get out of sync. Hence the term "synchronized" - among other things, this keyword forces a thread to get the most up-to-date version data that's accessed within the sync block, rather than rely on cached data which may be out of date. (You can also use the volatile keyword for this, but there are some subtle complications here; unless you really know what you're doing I'd advise using sync.)
If you don't use sync (or volatile), you could have scenarios where a user locks a record (using one thread), and then tries to update that record (using a different thread on the server, because RMI may freely assign different threads to different methods), and the second thread uses old cached info about the record's locking staus and expected cookie, and decides to throw a SecurityException even though the cookie provided is really completely valid. This sort of error is hard to replicate or track - you just get invalid illogical behaviour at odd times. The rule of thumb is: if you're accessing mutable data from multiple threads, do it from within a sync block. Unless you really, really know what you're doing.