I am trying to do a leader election problem with variable speed algorithm. I let one thread to be the master thread and multiple other threads to compete to be the leader. The thread with the largest id will become the leader, and the unique ids read from a input.dat are assigned to the threads. Each thread can only talk to its neighbors, it passes its id to its left or right neighbors, the neighbor will compare the received id and its own id and keep the larger one and forward it to the next neighbor. Finally, when one thread receives an id equal to its own id, that is must be the leader, then we can terminate the process.
In one round of the algorithm, each thread will have to wait for 2^(u - 1) rounds to pass its max_id_seen_so_far to its next direct neighbor according to the variable speed algorithm, where u is the max id the thread has seen so far. The master thread will start the xth round if all threads finished the (x - 1)th round. I use a counter as the flag, in each round, each thread will reduce the counter by one and wait. When the counter is 0, the master thread will be awaken and reset the counter to the number of the threads and signal all the threads for the new round.
class Ids {
private int[] ids;
private int number;
private boolean terminate;
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public boolean isTerminate() {
return terminate;
}
public void setTerminate(boolean terminate) {
this.terminate = terminate;
}
public int[] getIds() {
return ids;
}
public void setIds(int[] ids) {
this.ids = ids;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getOneId(int index) {
return this.ids[index];
}
public void setOneId(int index, int id) {
this.ids[index] = id;
}
@Override
public String toString() {
return "Ids [ids=" + Arrays.toString(ids) + ", number=" + number + "]";
}
}
class Process {
private Ids ids;
private int own_id;
private int max_id;
private int count;
private int index;
private int delay;
private Lock lock = new ReentrantLock();
private Condition masterCondition = lock.newCondition();
private Condition slaveryCondition = lock.newCondition();
public Process(Ids ids) {
super();
this.ids = ids;
}
public Process(Ids ids, int own_id, int index) {
super();
this.ids = ids;
this.own_id = own_id;
this.index = index;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public void runMaster() {
try {
while(true) {
lock.lock();
while(ids.getCount() != 0) {
masterCondition.await();
}
// work
ids.setCount(ids.getNumber());
slaveryCondition.signalAll();
if(ids.isTerminate()) {
return;
}
lock.unlock();
}
} catch (Exception e) {
}finally {
}
}
public void runSlavery() {
int size = ids.getNumber();
// get new id;
max_id = own_id;
delay = 0;
while(true) {
// wait for the start of the round, until the leader is found
int new_id = ids.getIds()[(index - 1) < 0 ? (size - 1) : (index - 1)];
if (new_id == own_id) {
ids.setTerminate(true);
break;
}
if(new_id > max_id) {
max_id = new_id;
delay = (int) Math.pow(2, new_id - 1);
}else {
// discard the new id;
if (delay == 0) {
// pass the max_id to the right neighbor
ids.setOneId(index, max_id);
delay = (int) Math.pow(2, max_id - 1);
}
delay--;
}
if (ids.isTerminate()) {
break;
}
try {
lock.lock();
ids.setCount(ids.getCount() - 1);
while(ids.getCount() > 0) {
slaveryCondition.await();
// Thread.sleep(1000);
System.out.println(ids.getCount());
}
// one round is over
masterCondition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
public class Variable_speed {
public static void main(String[] args) throws InterruptedException {
// Create a resource class
Ids ids = new Ids();
Scanner scanner;
try {
scanner = new Scanner(new File("data//input.dat"));
int n = scanner.nextInt();
int[] arr_id = new int[n];
for(int i = 0; i < n; i++) {
arr_id[i]= scanner.nextInt();
}
ids.setIds(arr_id);
ids.setNumber(n);
ids.setCount(n);
// Create a master thread
Process master = new Process(ids, -1, -1);
new Thread(() -> master.runMaster(), "master").start();
// create slavery threads
for(int i = 0; i < n; i++) {
Process process = new Process(ids, arr_id[i], i);
new Thread(() -> process.runSlavery(), "slavery").start();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
However, my concurrency program fails to awake the master thread when all the threads finish their first round, the program is stuck at the masterCondition.await(). I am not good at Java concurrency, please tell me where my problem is, I appreciate that.