3
\$\begingroup\$

I am using Java to modify remote files in different machines by ssh. At the same time, only one thread is allowed to modify the file in one machine.

I implement the logic like this:

public boolean executeCmd(String ip, String command, String file) throws Exception
{

    final String file = ip + " " + file;
    final String fileLock = file.intern();

    synchronized (fileLock)
    {
        logger.debug(Thread.currentThread().getName() + " " + fileLock + " get the lock");

        SSHClient sshClient = new SSHClient();

        // code to ssh to modify the file.

        logger.debug(Thread.currentThread().getName() + " " + fileLock + " release the lock");
    }
}

Then this function is called in tasks for multi-threads. Is this method satisfied for the purpose? I tested it for some simple cases and it seems to work OK.

At first, I lock the file using shell like this:

lockdir="$1.lock"
while ! mkdir "$lockdir" >/dev/null 2>&1
do
    echo "another process is running, wait..."
    sleep 10
done

trap 'rm -rf "$lockdir"' 0

There is a problem about this way. If the shell exits unexpectedly, the $lockdir will not be deleted, and it becomes a "deadlock".

I can't solve the problem so I lock the file using Java to ensure only one thread is modifying the same file.

\$\endgroup\$
2
\$\begingroup\$

According to your update, mkdir may be ok.

But a more official way is to use flock. You'd better to lock the file in the shell script. Locking using Java can't make any another process accessing the file.

Lock the file using flock in shell.

\$\endgroup\$
  • 1
    \$\begingroup\$ That's a good advice. However, you should also trap on other signals than zero in your shell script in order to make sure the lock is always cleaned up. \$\endgroup\$ – mkalkov Nov 10 '14 at 7:35
2
\$\begingroup\$

In the absence of different strings because of symlinks, hardlinks, multiple IPs for the same machine and hostnames instead of raw IPs, then yes, the synchronized combined with intern is thread-safe; no idea about performance, which is probably not an issue anyway.

If you only run all of this from a single program then it's probably okay in general, otherwise you should look into locking on the remote machines, i.e. constructing your command so that it locks on a .file.lock file or so.

\$\endgroup\$
  • \$\begingroup\$ Can you show me an example of how to construct the command to lock on a .file.lock file? Also, I update the question adding another way to lock the file by shell. \$\endgroup\$ – NingLee Nov 6 '14 at 1:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.