Java-跨多个文件的同步/锁定 [英] Java- Synchronization/Locking across multiple files

查看:120
本文介绍了Java-跨多个文件的同步/锁定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我将每个数据块"存储在一个单独的文件中.多个线程将同时读取和写入各种文件,因此我想避免由于未正确同步而导致的可能问题.本质上,我想要一个设置,其中每个文件的行为就像它具有自己的ReadWriteLock(两个线程可以同时写入两个不同的文件,但不能写入同一文件).我可以做到这一点(并做一些优化,其中ReadWriteLock仅在需要时实例化,而在不需要时销毁),但是我不确定这是正确的"事情.有更好的方法吗?

In my program, I will be storing each "block" of data in a separate file. Multiple threads will both read from and write to various files, and I want to avoid possible problems from not synchronizing this properly. Essentially, I want a setup where each file behaves as if it has its own ReadWriteLock (Two threads can write to two different files concurrently, but not to the same file). I could do just this (And do some optimizations where ReadWriteLocks are only instantiated when they are needed and destroyed when not), but I'm not sure that this is the "proper" thing to do. Is there a better way to do this?

我已经读到,使用FileLock在这种情况下不是是正确的选择,因为它只在不同的进程之间起作用,而在这种情况下不会做任何事情,因为所有我的线程处于同一进程中.

I've read that using a FileLock would not be the right thing to do in this situation, because it only matters between different processes, and would not do anything in this case because all of my threads are in the same process.

总结:我要避免的是让一个线程从一个文件中读取数据,从而使其他线程无法对许多其他文件执行任何操作.

To summarize: What I want to avoid is having one thread reading from one file locking out every other thread from doing anything with the many other files.

推荐答案

下面是一个示例singleton类,它提供了我认为您正在描述的大多数功能.它维护文件名到ReadWriteLocks的映射,并允许调用者根据文件名和READ/WRITE访问类型获取/释放锁.该类在首次使用时实例化锁,并向调用者隐藏锁对象,这应有助于您安全清除未使用的锁.

Here's an example singleton class that provides most of the functionality I think you are describing. It maintains a map of file names to ReadWriteLocks and allows callers to acquire/release a lock based on a file name and a READ/WRITE access type. The class instantiates locks on first use, and hides lock objects from the caller, which should help you to safely clean up locks that are not in use.

public enum LockRegistry {

// make our class a singleton
INSTANCE;

// map of file names to locks - You may want to change the keys to be File or
// something else, just be wary of the class's hashCode() semantics
private Map<String, ReadWriteLock> lockMap = new HashMap<String, ReadWriteLock>();

// lock to protect our registry - helps to prevent multiple threads
// from instantiating a lock with the same key
private Lock registryLock = new ReentrantLock();

// allow callers to specify the lock type they require
public enum LockType {
    READ, WRITE
}

public void acquire(String fileName, LockType type) {

    // lazily instantiates locks on first use
    ReadWriteLock lock = retrieveLock(fileName);

    switch (type) {
    case READ:
        lock.readLock().lock();
        break;
    case WRITE:
        lock.writeLock().lock();
        break;
    default:
        // handle error scenario
        break;
    }

}

public void release(String fileName, LockType type) {

    ReadWriteLock lock = retrieveLock(fileName);

    switch (type) {

    case READ:
        lock.readLock().unlock();
        break;
    case WRITE:
        lock.writeLock().unlock();
        break;
    default:
        // handle error scenario
        break;
    }

}

private ReadWriteLock retrieveLock(String fileName) {

    ReadWriteLock newLock = null;

    try {

        registryLock.lock();

        newLock = lockMap.get(fileName);

        // create lock and add to map if it doesn't exist
        if (newLock == null) {
            newLock = new ReentrantReadWriteLock();
            lockMap.put(fileName, newLock);
        }
    } finally {

        registryLock.unlock();
    }

    return newLock;
}

}

下面是一个简单的测试场景,用于显示LockRegistry的作用:

And here is a simple test scenario to show the LockRegistry in action:

public class LockTester implements Runnable {

private int id;
private String fileName;
private LockType type;

public LockTester(int id, String fileName, LockType type) {

    this.id = id;
    this.fileName = fileName;
    this.type = type;
}

@Override
public void run() {
    try {
        System.out.println("Consumer" + id + " acquiring " + type + " for "
                + fileName);
        LockRegistry.INSTANCE.acquire(fileName, type);

        System.out.println("Consumer" + id + " holding " + type + " for "
                + fileName);

        // hold the lock for 2 seconds
        Thread.sleep(2000);

    } catch (InterruptedException e) {

        e.printStackTrace();
    } finally {

        LockRegistry.INSTANCE.release(fileName, type);

        System.out.println("Consumer" + id + " release " + type + " for "
                + fileName);
    }
}

public static void main(String[] args) {

    List<Thread> testThreads = new ArrayList<Thread>();

    testThreads.add(new Thread(new LockTester(1, "file1", LockType.READ)));
    testThreads.add(new Thread(new LockTester(2, "file1", LockType.READ)));
    testThreads.add(new Thread(new LockTester(3, "file1", LockType.WRITE)));
    testThreads.add(new Thread(new LockTester(4, "file1", LockType.WRITE)));
    testThreads.add(new Thread(new LockTester(5, "file2", LockType.WRITE)));
    testThreads.add(new Thread(new LockTester(6, "file3", LockType.WRITE)));
    testThreads.add(new Thread(new LockTester(7, "file4", LockType.WRITE)));

    for (Thread t : testThreads) {
        t.start();
    }

}

}

希望这会有所帮助.

这篇关于Java-跨多个文件的同步/锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆