java - 许多作家一个读者没有并发

标签 java multithreading writer reader

我正在用Java编程,我有一个List<LogEntry> log,它在不同线程之间共享。

这些“writer”线程已经在它们之间同步,因此一次只有一个线程可以在log 中添加或删除元素。

但是,由于我要实现的分布式算法,日志的某些部分是“安全的”,这意味着它们既不能由作者也不能由读者修改(我将在下面介绍)。 log的这一部分由字段int committedIndex指示,该字段被初始化为0并单调增加。

总之,作者修改了log范围内(commitIndex,log.size())中的元素,而读者则获得了log范围内[0,commitIndex]中的元素。读者开始从第一个条目开始读取,然后阅读下一个条目,直到到达log.get(commitIndex)为止,然后停止并进入休眠状态,直到commitIndex增加。它会更新一个字段lastApplied,该字段被初始化为0,并单调递增,以便记住他在休眠前阅读的最后一个logEntry

如您所见,由于读取器和写入器访问log的不同部分,因此无需同步读取器和写入器。

我的问题是:增加commitIndex后,如何“唤醒”读者的线程?我需要这样的东西(由作家执行):

if(commitIndex is updated)
{
     //wake up reader
}

和读者:
public void run() {
    while(true){
        //go to sleeep...
        //now the reader is awaken!
        while(lastApplied<commitIndex){
            //do something with log.get(lastApplied)
            lastApplied++;
        }
    }

显然,我非常简化了我的代码,以使您尽可能地理解我想要的东西,如果它不够清晰,我感到很抱歉(不要犹豫,向我询问任何有关此问题的信息)。谢谢!

最佳答案

使用共享的 LinkedBlockingQueue<Integer> (在读者和所有作者之间),让每个作者向读者传达commitIndex变量已被修改的信号:

作家:

if (commitIndex is updated) {
    // wake up reader
    this.queue.add(commitIndex);
}

读者:
public void run() {
    while (true) {

        // take() puts this thread to sleep until a writer calls add()
        int commitIndex = this.queue.take();

        // now the reader is awaken!
        while (lastApplied < commitIndex) {
            // do something with log.get(lastApplied)
            lastApplied++;
        }
    }
}

在这里,我为读者和所有作者使用了queue属性,该属性应对应于LinkedBlockingQueue的相同实例。

注意:异常处理留作练习。

关于java - 许多作家一个读者没有并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28854953/

相关文章:

Java程序使用列表查找 'Lucky'从0到n的数字

Java关于I/O线程的调度机制

python-3.x - python 3 如何使用 csv writer 编写 utf-8

api - LibreOffice Writer API - VB6 中的光标和文本选择/替换

java - 不关闭 BufferedWriter 的后果是什么

java - 哪个 Java 集合适合在巨大的数组列表中查找具有最大时间戳的文件名?

java - 如何将 Intellij 查找用法的结果限制为仅特定类的结果?

java - 同步有什么问题

python - 如何在 x 分钟后暂停该线程

c# - kernel32.dll Sleep 和 Thread.Sleep() 之间的任何区别