Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 许多作者都是一个读者而没有并发_Java_Multithreading_Writer_Reader - Fatal编程技术网

Java 许多作者都是一个读者而没有并发

Java 许多作者都是一个读者而没有并发,java,multithreading,writer,reader,Java,Multithreading,Writer,Reader,我正在用java编程,我有一个列表日志,它在不同的线程之间共享 这些“编写器”线程已经在它们之间同步,因此每次只有一个线程可以从日志中添加或删除元素 然而,由于我试图实现的分布式算法,日志中有一部分是“安全的”,这意味着作者或读者都不能修改它们(我将在下面介绍)。log的这一部分由字段int committedIndex表示,该字段初始化为0并单调递增 总之,编写者修改范围(commitIndex,log.size())中的log中的元素,而有一个读卡器获取范围[0,commitIndex]中包

我正在用java编程,我有一个
列表日志
,它在不同的线程之间共享

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

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

总之,编写者修改范围
(commitIndex,log.size())
中的
log
中的元素,而有一个读卡器获取范围
[0,commitIndex]
中包含的
log
中的元素。读取器从第一个条目开始读取,然后读取下一个条目,直到到达
log.get(commitIndex)
,然后它停止并进入睡眠状态,直到
commitIndex
增加。它更新一个字段
lastapplicated
,该字段初始化为0并单调增加,以便记住他睡觉前读取的最后一个
logEntry

如您所见,不需要同步读卡器和写卡器,因为它们访问
日志的不同部分

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

读者:

public void run() {
    while(true){
        //go to sleeep...
        //now the reader is awaken!
        while(lastApplied<commitIndex){
            //do something with log.get(lastApplied)
            lastApplied++;
        }
    }
public void run(){
while(true){
//去斯里普。。。
//现在读者觉醒了!
虽然(上次应用尝试以下方法:

if(commitIndex已更新)
{
//唤醒阅读器
同步(读卡器)
{
reader.notify();
}
}
使用共享(在读卡器和所有写卡器之间)让每个写卡器向读卡器发出信号,表明
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++;
        }
    }
}
阅读器:

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++;
        }
    }
}
public void run(){
while(true){
//take()使该线程处于睡眠状态,直到编写器调用add()为止
int commitIndex=this.queue.take();
//现在读者觉醒了!
while(上次应用<提交索引){
//使用log.get(lastApplied)执行某些操作
lastApplied++;
}
}
}
在这里,我使用了属性
queue
,对于读卡器和所有写卡器,它应该对应于
LinkedBlockingQueue
的相同实例


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

一些wait()和notify()示例:可以,但是读取器的
run()
方法应该声明为已同步,对吗?您的解决方案对于该问题不可行,原因有多种:1.共享对象是
LogEntry
对象的列表(正如我在问题的开头所说的),而不是int的列表。因此(最终)队列应该包含
LogEntry
而不是
Integer
对象。2.我注意到我没有写到读者都不能修改日志的“safe”(committed)部分,所以使用队列(其中
take()
操作移除队列头)是不允许的。在addiction中,我需要一个实现随机访问操作的结构(例如
列表或
数组)。顺便说一句,谢谢:)@justHelloWorld我不是建议您更改
LogEntry
列表,继续使用该列表。这个
Integer
s队列仅用于向读者发出信号。很抱歉,我上面的评论,我没有得到您的解决方案。我认为您的解决方案是完全正确的,但我发现@marchew one更优雅,因为它没有除非你说服我,否则不要引入任何新的支持结构。@justHelloWorld@marchew解决方案的缺点是,你需要使用
synchronized
块来等待和通知,以及将
commitIndex
声明为
volatile
。对于队列,你不需要这样的东西,因为它会d处理同步。它还可以让您以简单的方式在线程之间传输
commitIndex
。@justHelloWorld如果您不喜欢引入新结构的想法,可以使用。这样可以避免
synchronized
块,但仍需要将
commitIndex
声明为
vola平铺
,并在线程之间传递。从:“如果多个线程同时访问链接/数组列表,并且至少有一个线程在结构上修改了该列表,则必须在外部对其进行同步。”请注意,必须强调的是:您认为从较低索引读取而向较高索引写入是正确的假设是无效的。列表只能在未被读者利用的部分中进行结构修改。因此,读者和作者之间没有共享,只能在作者之间共享(实际上是同步的)