liquibase-cdi/src/main/java/liquibase/integration/cdi/SchemesCDIConfigBuilder.java
CDILiquibaseConfig fileLocked(final String id, Callable<CDILiquibaseConfig> action) throws Exception {
        log.info(LogType.LOG, String.format("[id = %s] JVM lock acquired, acquiring file lock", id));
        String lockPath = String.format("%s/schema.liquibase.lock", ROOT_PATH);

        File lockFile = new File(lockPath);
        if (!lockFile.exists() && lockFile.createNewFile()) {
            log.info(LogType.LOG, String.format("[id = %s] Created lock file [path='%s'].", id, lockPath));
        }

        log.info(LogType.LOG, String.format("[id = %s] Trying to acquire the file lock [file='%s']...", id, lockPath));

        CDILiquibaseConfig actionResult = null;
        FileLock lock = null;
        try (
            FileOutputStream fileStream = new FileOutputStream(lockPath);
            FileChannel fileChannel = fileStream.getChannel();
        )
        {
            while (null == lock) {
                try {
                    lock = fileChannel.tryLock();
                } catch (OverlappingFileLockException e) {
                    log.fine(LogType.LOG, String.format("[id = %s] Lock already acquired, waiting for the lock...", id));
                }
                if (null == lock) {
                    log.fine(LogType.LOG, String.format("[id = %s] Waiting for the lock...", id));
                    Thread.sleep(FILE_LOCK_TIMEOUT);
                }
            }
            log.info(LogType.LOG, String.format("[id = %s] File lock acquired, running liquibase...", id));
            actionResult = action.call();
            lock.release();
        } catch (Exception e) {
            log.warning(LogType.LOG, e.getMessage(), e);
        }
        return actionResult;
    }
CDILiquibaseConfig fileLocked(final String id, Callable<CDILiquibaseConfig> action) throws Exception {
        log.info(LogType.LOG, String.format("[id = %s] JVM lock acquired, acquiring file lock", id));
        String lockPath = String.format("%s/schema.liquibase.lock", ROOT_PATH);

        File lockFile = new File(lockPath);
        if (!lockFile.exists() && lockFile.createNewFile()) {
            log.info(LogType.LOG, String.format("[id = %s] Created lock file [path='%s'].", id, lockPath));
        }

        log.info(LogType.LOG, String.format("[id = %s] Trying to acquire the file lock [file='%s']...", id, lockPath));

        CDILiquibaseConfig actionResult = null;
        FileLock lock = null;
        try (
            FileOutputStream fileStream = new FileOutputStream(lockPath);
            FileChannel fileChannel = fileStream.getChannel();
        )
        {
            while (null == lock) {
                try {
                    lock = fileChannel.tryLock();
                } catch (OverlappingFileLockException e) {
                    log.fine(LogType.LOG, String.format("[id = %s] Lock already acquired, waiting for the lock...", id));
                }
                if (null == lock) {
                    log.fine(LogType.LOG, String.format("[id = %s] Waiting for the lock...", id));
                    Thread.sleep(FILE_LOCK_TIMEOUT);
                }
            }
            log.info(LogType.LOG, String.format("[id = %s] File lock acquired, running liquibase...", id));
            actionResult = action.call();
            lock.release();
        } catch (Exception e) {
            log.warning(LogType.LOG, e.getMessage(), e);
        }
        return actionResult;
    }
Synchronization among multiple JVM's.