有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java多个编写器一个读取器而不并发

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

这些“编写器”线程已经在它们之间同步,因此每次只有一个线程可以添加或删除log

然而,由于我试图实现的分布式算法,日志中有一部分是“安全的”,这意味着作者或读者都不能修改它们(我将在下面介绍)。这部分log由字段int committedIndex表示,该字段初始化为0并单调递增

总之,编写器修改了范围(commitIndex,log.size())内的log中的元素,而有一个读取器获取范围[0,commitIndex]中包含的log中的元素。读取器从第一个条目开始读取,然后读取下一个条目,直到到达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++;
        }
    }

显然,为了让您尽可能更好地理解我想要的内容,我非常简化了我的代码。如果不够清楚,我很抱歉(请不要犹豫,向我询问任何相关信息)。谢谢


共 (2) 个答案

  1. # 1 楼答案

    试试这个:

    if(commitIndex is updated)
    {
      //wake up reader
      synchronized(reader)
      {
        reader.notify();
      }
    }
    
  2. # 2 楼答案

    使用共享的^{}(在读卡器和所有写卡器之间)让每个写卡器向读卡器发出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的同一个实例,用于读者和所有作者

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