/**
@author Administrator
*
*/
public class BB {
private int increment = 0;
final static Set set = new HashSet();
final static List list = new ArrayList();
public synchronized int getauto() {
return increment++;
}
public static void main(String[] args) throws Exception {
final BB b = new BB();
Vector workers = new Vector();
for (int i = 0; i < 2; i++) {
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
synchronized (this) {
for (int j = 0; j < 10000; j++) {
int num = b.getauto();
System.out.println(String.valueOf(num));
set.add(num);
list.add(num);
}
}
}
});
workers.add(t);
t.setName("thread-" + i);
t.start();
}
for (Thread t : workers) {
t.join();
}
System.out.println("set size :" + set.size());
System.out.println("list size :" + list.size());
}
}
list和set的size不同
System.out.println("set size :" + set.size());
System.out.println("list size :" + list.size());
这两句可没有在锁区域内,一个线程完毕后,在这两句执行的任意时刻,另一个线程可能已经开始执行,并改写了list
for (Thread t : workers) {
t.join();
}
这个是等待线程都执行完毕
System.out.println("set size :" + set.size());
System.out.println("list size :" + list.size());
这两句肯定是线程都执行完了,才打印出来的。预期结果set和list的size都是20000
hashset、arraylist是线程不安全的,你这样写,有时候会得到正确的长度。同步一下就好。。
你的工作线程的run方法中synchronize是用的this,是指当前线程对象,这样的话,每个线程都是有自己的this对象,所有线程run时锁都不一样,怎么能保证对共享变量的同步呢?那必定会出现同时操作set和list共享变量的情况啊
修正代码,使用外界共享对象作为锁,例如用final BB b,或者直接对list和set进行加锁,就能保证run中的代码每次只有一个线程能获取到锁。
synchronized (b) {
for (int j = 0; j < 10000; j++) {
int num = b.getauto();
System.out.println(String.valueOf(num));
set.add(num);
list.add(num);
}
}
这个问题,主要是每个工作线程在run中用的锁不同,你的代码锁在线程对象this上,就相当于根本没有同步处理。