在线程

时间:2017-12-07 11:36:51

标签: java multithreading

有一个主列表,其中每个条目都包含一个字符串数组。还有一个从属列表,它实际上是一个散列集,每个条目都是一个字符串。我写了两个线程来搜索主列表中从属列表中的项目。

有一个stat的成员类,我在发出线程之前初始化它(而不是构造函数)。当他想要搜索主列表中的从属项时,每个线程将stat递增1。

在实际代码中,每个线程的主列表都是唯一的,以下示例代码使用一个主列表用于两个线程。

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();
  }
}

然而输出看起来很奇怪!!

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

第二行应打印stat=2。似乎这里存在并发问题。第二个线程读取stat的旧值,即0,但第一个线程必须在第二个线程之前将其递增1。

另一次运行的输出是

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

如您所见,统计数据在第一行打印为2! 怎么解决?

2 个答案:

答案 0 :(得分:1)

您的代码确实存在同步问题。

您可能希望使用synchronized块来访问stat变量。

查看documentation

答案 1 :(得分:1)

您可以同步使用共享变量的部分:

  while(itr.hasNext()){
    int localStat;
    synchronized(this) {
        localStat = ++stat;
    }
    System.out.println("index=" + index + " master id=" + x + " slave=" + itr.next() + " stat=" + localStat );
  }

但这些名单仍然是共享的,没有受到保护。