Reputation: 24705
There is a master list where each entry contains a string array. There is also a slave list which is actually a hash set and each entry is a string. I have wrote two threads to search an item from the slave list in the master list.
There is a member class for stat and I initialize it right before issuing the threads (and not the constructor). Each thread increments the stat by 1 when he wants to search a slave item in the master list.
While in the real code, the master list for each thread is unique, the following sample code uses one master list for two threads.
class myClass {
private List<String []> mainList;
private HashSet<String> slaveList;
private int nThread;
private int stat;
public myClass(int i)
{
nThread = i;
mainList = new ArrayList<>();
slaveList = new HashSet<>();
String [] str1 = {"a1", "a2", "a3"};
String [] str2 = {"b1", "b2", "b3"};
mainList.add(str1); mainList.add(str2);
slaveList.add("b2"); slaveList.add("a3");
}
public void doProcess() {
stat = 0;
for (int i = 0; i < nThread; i++) {
final int index = i;
final List<String []> m = mainList;
final HashSet<String> s = slaveList;
new Thread(() -> {
search(m, s, index);
System.out.println("done");
}).start();
}
}
public void search( List<String []> m, HashSet<String> s, int index )
{
Iterator<String> itr;
for ( int x = 0; x < m.size(); x++ ) {
itr = s.iterator();
while(itr.hasNext()){
++stat;
System.out.println("index=" + index + " master id=" + x + " slave=" + itr.next() + " stat=" + stat);
}
}
}
}
public class Threadtest {
public static void main(String[] args) {
myClass mc = new myClass(2);
mc.doProcess();
}
}
The output however looks odd!!
index=0 master id=0 slave=b2 stat=1
index=1 master id=0 slave=b2 stat=1
index=0 master id=0 slave=a3 stat=2
index=1 master id=0 slave=a3 stat=3
index=0 master id=1 slave=b2 stat=4
index=1 master id=1 slave=b2 stat=5
index=0 master id=1 slave=a3 stat=6
index=1 master id=1 slave=a3 stat=7
done
done
The second line should print stat=2
. It seems that there is a concurrency issue here. The second thread reads the old value of stat
which is 0 but the first thread had to increment it by 1 before the second thread.
The output of another run is
index=0 master id=0 slave=b2 stat=2
index=0 master id=0 slave=a3 stat=3
index=0 master id=1 slave=b2 stat=4
index=1 master id=0 slave=b2 stat=2
index=0 master id=1 slave=a3 stat=5
index=1 master id=0 slave=a3 stat=6
done
index=1 master id=1 slave=b2 stat=7
index=1 master id=1 slave=a3 stat=8
done
As you can see, the stat is printed as 2 on the first line!! How that can be fixed?
Upvotes: 1
Views: 66
Reputation: 9651
You could synchronize the part where you use the shared variable:
while(itr.hasNext()){
int localStat;
synchronized(this) {
localStat = ++stat;
}
System.out.println("index=" + index + " master id=" + x + " slave=" + itr.next() + " stat=" + localStat );
}
But the lists are still shared and unprotected.
Upvotes: 1
Reputation: 14607
It sure is a synchronization problem in your code.
You might want to use synchronized
block for accessing stat
variable.
Take a look at the documentation.
Upvotes: 1