多个读取器和多个写入器(我的意思是多个)同步

时间:2013-06-22 15:00:49

标签: unix concurrency synchronization operating-system locking

我正在开发一种需要读/写锁定变体的功能,可以允许并发多个写入器。

标准读/写锁允许多个读取器或单个写入器同时运行。我需要一个可以同时允许多个读者或多个作者的变体。因此,它不应该同时允许读者和作者。但是,可以同时允许多个作者或同时允许多个读者。

我希望我很清楚。到目前为止我找不到任何现有的算法。我可以想办法使用一些队列等来做这些事情。但是,我不想冒险自己做,除非不存在。

你们知道现有的计划吗?

谢谢,

3 个答案:

答案 0 :(得分:0)

如果您使用的是pthread,请查看this question中的同步方法。

您可以使用两个变量readerCountwriterCount以及互斥锁的类似方法。 在读者线程中,您将锁定互斥锁并等待writerCount == 0。如果满足条件,则将readerCount递增1并释放锁定。然后你做阅读。完成后,再次锁定互斥锁,递减readerCount,指示条件发生变化并释放锁定。

编写器线程遵循相同的逻辑,但是等待条件readerCount == 0并递增/递减writerCount

答案 1 :(得分:0)

我确实有一个Nifs评论的解决方案。我在下面发布了我的解决方案。问题在于公平政策。饥饿很容易发生。在我的方法中,一种线程不太可能比其他线程。所以我只是优先考虑女孩。理想情况下,我们希望这是一个体面的公平政策。

/**
 * RestRoomLock:
 *
 * This lock tries to simulate a gender based access to common rest room.
 * It is okay to have multiple boys or multiple girls inside the room. But,
 * we can't have boys and girls at the same time inside the room.
 *
 * This implementation doesn't really have proper fairness policy. For now,
 * girls are being treated with priority as long as boys are being gentle,
 * boyEntryBeGentle();
 *
 * @author bmuppana
 */
public class RestRoomLock {
    int boysInside;
    int girlsInside;
    int girlsWaiting;


    RestRoomLock() {
        boysInside = girlsInside = girlsWaiting = 0;
    }

    public synchronized void boyEntry() {
        while (girlsInside > 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        boysInside++;
    }

    public synchronized void boyEntryBeGentle() {
        while (girlsInside + girlsWaiting > 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        boysInside++;
    }

    public synchronized void boyExit() {
        boysInside--;
        assert boysInside >= 0;

        notifyAll();
    }

    public synchronized void girlEntry() {
        girlsWaiting++;
        while (boysInside > 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        girlsWaiting--;

        girlsInside++;
    }

    public synchronized void girlExit() {
        girlsInside--;
        assert girlsInside >= 0;

        notifyAll();
    }
}

答案 2 :(得分:0)

您正在寻找的概念是重入锁定。如果已经锁定,则需要能够尝试获取锁定并且不会被阻止(这称为可重入锁定)。在java中有一个可重入锁的本机实现,所以我将用Java来说明这个例子。 (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html)。

因为当使用tryLock()时,如果锁定不可用,则不会阻止您的编写器/阅读器继续。但是,当您确定没有人正在读/写时,您只想释放锁定,因此您需要保留读者和作者的数量。您将需要同步此计数器或使用允许原子递增/递减的本机atomicInteger。对于这个例子,我使用了原子整数。

Class ReadAndWrite {
 private ReentrantLock readLock;
 private ReentrantLock writeLock;
 private AtomicInteger readers;
 private AtomicInteger writers;
 private File file;

 public void write() {
   if (!writeLock.isLocked()) {
    readLock.tryLock();
    writers.incrementAndGet(); // Increment the number of current writers
    // ***** Write your stuff *****
    writers.decrementAndGet(); // Decrement the number of current writers
    if (readLock.isHeldByCurrentThread()) {
     while(writers != 0); // Wait until all writers are finished to release the lock
     readLock.unlock();
    }
   } else {
     writeLock.lock();
     write();
   }
  }

 public void read() {
   if (!readLock.isLocked()) {
    writeLock.tryLock();
    readers.incrementAndGet(); 
    // ***** read your stuff *****
    readers.decrementAndGet(); // Decrement the number of current read
    if (writeLock.isHeldByCurrentThread()) {
     while(readers != 0); // Wait until all writers are finished to release the lock
     writeLock.unlock();
    }
   } else {
     readLock.lock();
     read();
   }
  }

这里发生了什么:首先,检查您的锁是否已锁定,以了解您是否可以执行您要执行的操作。如果它被锁定则表示您无法读取或写入,因此您使用锁定使自己处于等待状态,并在再次释放锁定时重新调用相同的操作。

如果它没有被锁定,那么你使用tryLock锁定另一个动作(如果你要读锁定写,反之亦然)。 tryLock如果已经锁定则不会阻塞,因此几个编写者可以同时写入并且几个读者可以同时读取。当你做同样事情的线程数达到0时,这意味着谁拥有锁头的人现在可以释放它。这个解决方案唯一的不便是持有锁的线程必须保持活着,直到每个人都完成才能释放它。