两种方法之间的锁定使一种方法匮乏

时间:2015-01-08 09:02:25

标签: java file-io concurrency synchronization

在我的程序中,我有两种方法:

public void methodA() { //gets called very often
   //write something to file
}

public void methodB() {
  //write something to file
}

methodA经常被客户端调用,而methodB只会不时调用。但是,我需要确保无论何时客户端想要调用methodB它都可以这样做(在methodA可能的当前执行完成之后)。我尝试在每个方法中引入一个带锁定对象的同步块,但methodB似乎饿死了,因为methodA被更频繁地调用。 我该如何解决这个问题?

7 个答案:

答案 0 :(得分:10)

听起来你需要一个公平 Lock。要制作其中一个,您应该将true作为参数传递给构造函数。

Lock lock = new ReentrantLock(true);

public void methodA() {
    lock.lock();
    try {
        // Write something to a file.
    } finally {
        lock.unlock();
    }
}

public void methodB() {
    lock.lock();
    try {
        // Write something to a file.
    } finally {
        lock.unlock();
    }
}

答案 1 :(得分:2)

ReentrantLock有一个constructor,其中包含一个公平参数,可以防止你的情况出现饥饿。

答案 2 :(得分:2)

如果你想优先考虑方法B而不是方法A,这是我能想到的最简单的事情:

private Object writeLock = new Object();
private Object highPriorityLock = new Object();
private int highPriorityLockReleaseCount = 0;
private int highPriorityLockLockCount = 0;

public void methodA() {
    synchronized (writeLock) {
        synchronized (highPriorityLock) {
            // Wait until there are no more highPriorityLocks
            while (highPriorityLockLockCount != highPriorityLockReleaseCount) {
                highPriorityLock.wait();
            }
        }
        // Do write (thread holds write lock)
    }
}

public void methodB() {
    synchronized (highPriorityLock) {
        // Get current lock count
        int lockCount = highPriorityLockLockCount;
        // Increment lock count by one
        highPriorityLockLockCount++;
        // Wait until lock is acquired (current release count reaches saved lock count)
        while (lockCount != highPriorityLockReleaseCount) {
            highPriorityLock.wait();
        }
    }
    synchronized (writeLock) {
        // Do write (thread holds write lock)
    }
    synchronized (highPriorityLock) {
        // Relase high priority lock by incrementing current counter
        highPriorityLockReleaseCount++;
        highPriorityLock.notifyAll();
    }
}

确保处理异常并确保始终正确释放高优先级锁

答案 3 :(得分:1)

我建议优先处理队列。简单地说,有两个队列,一个用于方法A,另一个用于方法B.在下面的逻辑中处理队列的另一个线程:当B的队列不为空时,操作它,否则,为A队列。

答案 4 :(得分:1)

您可以使用semaphores。它基本上适用于你将字段设置为某个值的想法。让我们说锁定。而另一种方法,你做了一段时间..重复无限,直到其他过程完成。您可以通过在diffirent线程中调用该方法来使用信号量。并使用关键字synchronized void ..

信号量部分是硬件部分软件解决方案。还有纯软件解决方案。例如Peterson's algorithm

答案 5 :(得分:1)

如果您的主要问题是methodB来电不被阻止或者饿死,您可以通过非阻塞I / O操作来解决并发问题

Java NIO.2 java.nio.channels.AsynchronousFileChannel可以满足这些需求。您可以找到一个很好的用法说明和示例here

答案 6 :(得分:0)

这与this question大致相同。该问题的最高评价答案有三种选择。选项2和3都假设methodB将始终从同一个线程调用,您没有说过这种情况,但选项1应该有效。移植到Java的选项1是:

private final Lock m = new ReentrantLock();
private final Lock n = new ReentrantLock();
private final Lock l = new ReentrantLock();

public void methodA() {
    l.lock();
    n.lock();
    m.lock();
    n.unlock();
    try {
        doA();
    } finally {
        m.unlock();
        l.unlock();
    }
}

public void methodB() {
    n.lock();
    m.lock();
    n.unlock();
    try {
        doB();
    } finally {
        m.unlock();
    }
}

这给方法B绝对优先于方法A,不像OldCurmudgeon的答案,它给出了两个相同的优先级。如果您还希望算法公平(除了methodB优先于methodA),您应该使锁nl公平。 m的公平性并不重要。