我正在研究并发运行的算法。它使用队列扩展平坦组合算法。问题是程序大部分时间运行正常,但每10次运行就会陷入无限循环。我尝试添加打印但是当我这样做时它不会进入无限循环。它循环多次以在调试模式下跟随它。 如果你能通过看到可能导致无限循环的场景来帮助我,我会非常感激。
package main;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class MppRunner {
FlatCombiningQueue<Integer> queue;
enum Operation {
ENQUEUE, DEQUEUE, NONE
};
public MppRunner(int num) {
queue = new FlatCombiningQueue<Integer>(8);
}
public static void main(String[] args) throws Exception {
MppRunner m = new MppRunner(8);
Random rand = new Random();
Thread[] thread = new Thread[8];
AtomicInteger j = new AtomicInteger(0);
AtomicInteger k = new AtomicInteger(0);
AtomicInteger s = new AtomicInteger(0);
for (int i = 0; i < 8; i++) {
thread[i] = new Thread() {
int i;
public void run() {
while ((i = j.getAndIncrement()) < 1000000) {
// System.out.printf("i is: %d\n", i);
if (rand.nextInt() % 2 == 0) {
try {
m.queue.enqueue(i);
k.getAndIncrement();
} catch (Exception e) {
System.out.println("boom");
e.printStackTrace();
}
} else {
try {
if (m.queue.dequeue() != null)
s.getAndIncrement();
} catch (Exception e) {
System.out.println("boom");
e.printStackTrace();
}
}
}
}
};
}
double start = System.currentTimeMillis();
for (int i = 0; i < 8; i++)
thread[i].start();
for (int i = 0; i < 8; i++)
thread[i].join();
System.out.println("time = " + (System.currentTimeMillis() - start));
while (m.queue.dequeue() != null)
s.getAndIncrement();
System.out.println(k + " = " + s);
}
public class FlatCombiningQueue<T> {
volatile int numberOfThread;
AtomicBoolean lock;
AtomicReference<PublicationListNode> PublicationListHead;
volatile QueueNode head;
volatile QueueNode tail;
volatile ArrayList1<PublicationListNode> localRecordArray;
FlatCombiningQueue(int numberOfThread) {
this.numberOfThread = numberOfThread;
lock = new AtomicBoolean(false);
PublicationListHead = new AtomicReference<PublicationListNode>(null);
head = null;
tail = null;
localRecordArray = new ArrayList1<PublicationListNode>(
numberOfThread);
}
public T dequeue() {
int id = (int) Thread.currentThread().getId() % numberOfThread;
if (localRecordArray.get(id) == null)
createLocalNode(id);
PublicationListNode temp = localRecordArray.get(id);
temp.operation = Operation.DEQUEUE;
localRecordArray.set(id, temp);
if (lock.compareAndSet(false, true)) {
// do {
executeMethods();
lock.set(false);
} else
while (localRecordArray.get(id).operation == Operation.DEQUEUE)
;
return localRecordArray.get(id).value;
}
public void enqueue(T value) {
int id = (int) Thread.currentThread().getId() % numberOfThread;
if (localRecordArray.get(id) == null)
createLocalNode(id);
PublicationListNode temp = localRecordArray.get(id);
temp.value = value;
temp.operation = Operation.ENQUEUE;
localRecordArray.set(id, temp);
if (lock.compareAndSet(false, true)) {
// do {
executeMethods();
lock.set(false);
// } while (!PublicationListHead.get().first
// && lock.compareAndSet(false, true));
} else
while (localRecordArray.get(id).operation == Operation.ENQUEUE)
;
}
public void createLocalNode(int id) {
PublicationListNode newHead = new PublicationListNode();
newHead.first = true;
PublicationListNode oldHead;
localRecordArray.set(id, newHead);
do {
oldHead = PublicationListHead.get();
newHead.next = oldHead;
} while (!PublicationListHead.compareAndSet(oldHead, newHead));
if (oldHead != null)
oldHead.first = false;
}
public void executeMethods() {
PublicationListNode current = PublicationListHead.get();
while (current != null) {
if (current.operation == Operation.DEQUEUE)
applyDequeue(current);
else if (current.operation == Operation.ENQUEUE)
applyEnqueue(current);
current = current.next;
}
}
private void applyDequeue(PublicationListNode current) {
if (tail == null)
current.value = null;
else {
current.value = tail.value;
tail = tail.next;
if (tail == null)
head = null;
}
current.operation = Operation.NONE;
}
private void applyEnqueue(PublicationListNode current) {
QueueNode node = new QueueNode(current.value);
if (head != null) {
head.next = node;
head = head.next;
} else {
head = node;
tail = head;
}
current.operation = Operation.NONE;
}
public class ArrayList1<E> {
private E array[];
@SuppressWarnings("unchecked")
ArrayList1(int numberOfThread) {
array = (E[]) new Object[numberOfThread];
}
public E get(int i) {
return array[i];
}
public void set(int i, E value) {
array[i] = value;
}
}
public class PublicationListNode {
volatile Boolean first;
volatile Operation operation;
volatile T value;
PublicationListNode next;
public PublicationListNode() {
first = false;
operation = Operation.NONE;
value = null;
next = null;
}
}
public class QueueNode {
volatile T value;
volatile QueueNode next;
QueueNode(T value) {
this.value = value;
next = null;
}
}
}
}