我需要实现一个共识协议,该协议使用带有peek()方法的队列,以显示可以为任意数量的线程达成共识,即具有peek()方法的队列具有无限的共识号
这是我的代码
import java.util.LinkedList;
import java.util.Queue;
public class PeekConsensus extends ConsensusProtocol<Integer>
{
Queue<Integer> queue ;
public PeekConsensus(int threadCount)
{
super(threadCount); //threadCount is a command line argument from the main class specifying the number of threads to handle this process
queue = new LinkedList<Integer>() //FIFO queue
}
public Integer decide(Integer value)
{
this.propose(value); // stores "value" in a vector named proposed, at index ThreadID.get()
int i = ThreadID.get() ;
queue.add(i)
System.out.println("Thread " + i + " : " + i) ; // Required by specifications to print thread id and the value added when an item is enqueued
System.out.println("Thread " + i + " : " + queue.peek()) ; // Required by specifications to print thread id and the value of peek() when when peek() is called
return proposed.elementAt(queue.peek()) ;
}
}
从我的理解,这应该工作,因为如果两个线程返回不同的值,peek()将必须返回不同的线程ID并确保有效性,因为每个线程在推送其线程ID之前将其自己的值写入建议。
是否有人能够找出我出错的地方并指导我纠正我的代码
答案 0 :(得分:2)
该协议对我来说很好。但你有没有想过如何实现peek()
?
由于peek()
实际上是pop()
后跟push()
,因此我们可以在此代码中进行错误的交错。
假设peek()
可以原子方式执行,则该共识协议将起作用。
如何更改?
只是你的代码运行,你可以将synchronized
添加到peek()
,但这会破坏共识协议的目的,因为线程可能会死,持有锁。
尝试使用AtomicReference
。这允许您以原子方式获取,甚至设置值。在这种情况下,指针将是head
。
现在问题出现了:AtomicReference
如何在Java中实现。不幸的是,它是使用CAS
实现的,它再次只会使用FIFO队列来破坏共识协议的目的。
最后:正式地,FIFO队列具有共识编号2.假设peek()
以原子方式执行,您的协议是有效的。但是,正确的实施需要某种CAS
或synchronized
。