-
怎么使用 ConcurrentHashMap 才能是线程安全的?
package util; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class test { public static Map<String, Integer> chm = new ConcurrentHashMap<String, Integer>(); public static void main(String[] args) { test.chm.put("test", 1); tht t1 = new tht(); t1.start(); for (int i = 1; i < 1000; i++) { th t = new th(i); t.start(); } } } class th extends Thread { private int number = 0; public th(int _number) { number = _number; } @Override public void run() { boolean bo = true; while (bo) { int state = 0; state = (Integer) test.chm.get("test"); if (state == 9) { System.out.println("线程:" + number + ",停止!"); bo = false; } else { System.out.println("线程:" + number + ",state=" + state + ",time:" + System.currentTimeMillis()); } } } } class tht extends Thread { public tht() { } @Override public void run() { boolean bo = true; while (bo) { int state = 0; state = (int) (Math.random() * 1000000); test.chm.put("test", state); if (state == 9) { System.out.println("线程:-1,停止,time=" + System.currentTimeMillis() + ",--------------------------------------------"); bo = false; } } } }
运行多次运行后出现结果:
线程:237,state=178474,time:1348219230671
线程:-1,停止,time=1348219230671,--------------------------------------------
线程:236,state=178474,time:1348219230671
线程:337,state=178474,time:1348219230671
线程:876,state=178474,time:1348219230671
ConcurrentHashMap不是线程安全的么,那么多个线程同时读和改的时候,从运行结果看改的线程获取到锁以后,读的线程还是可以继续执行的.到底怎么使用ConcurrentHashMap才能保证数据一致?
问题补充:正常应该是,改state赋值为9后,所有读线程停止工作.但改的线程put时,读的线程并没有等待放锁后在读呢?
解答:
我不知道这位兄台有没有测试过,加不加synchronized效果是一样的;本身ConcurrentHashMap本身就是线程安全的,这个安全只存在于put和get操作,之所以出现楼主这种情况,就是你说的线程调度问题,楼主把这个//System.out.println("线程:"+number+",停止!"); 去掉注释后运行,是不是可以看到所有的线程最终停止了;前面多了些 线程:236,state=178474,time:1348219230671 线程:337,state=178474,time:1348219230671 线程:876,state=178474,time:1348219230671 这样的信息,为什么? 那是因为在chm被插入9之前,有些线程比如A线程运行到int state = (Integer)test.chm.get("test"); 此时得到state不是9,线程调度切换到插入9的线程B,此test.chm被插入9,B结束;切换为A继续执行,发什么什么,打印了这句: 线程:236,state=178474,time:1348219230671 因为这里的state是插入9之前的值; 什么时候结束,下一次循环重新得到的state就是9了。 所以说不论加不加synchronzied都会出现这种效果,线程调度的问题; 总结: (1)ConcurrentMap是线程安全的,这种安全只存在于对他自己的操作,不能保证外部; (2)线程调度可能引起开始错误的结果。
-
======================To be Continued======================