日期:2014-05-20  浏览次数:20739 次

Java 多线程问题
请看如下代码:
开启两个线程对count执行加运算,按道理两个线程运行完以后,count不是应该加了2000000次吗?怎么结果打印没有200000呢?

public class ThreadDemo {

class RunnableImpl implements Runnable{
int count=0;
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100000;i++){

count++;

System.out.println(Thread.currentThread().getName()+":"+count);
}
}

}
public static void main(String[] args) {
ThreadDemo demo=new ThreadDemo();
RunnableImpl impl=demo.new RunnableImpl();
Thread t1=new Thread(impl,"线程1");
Thread t2=new Thread(impl,"线程2");
t1.start();
t2.start();
}

}

多试几次,结果都不尽相同,反正想了解为什么结果count没有200000.
高手请指教!



------解决方案--------------------
应该在run方法里加个同步代码块
------解决方案--------------------
多个进程同时访问一个公共资源,可能会造成公共资源破坏
在某一时刻,两个进程同时对count加一,加之前count假设是20,加一之后就是21
本该是22的,但是结果就是21,以后也有可能发生类似事件,所以造成结果不是200000,而且结果肯定不大于200000
------解决方案--------------------
两个线程争用同一个count对象当然会出问题的,程序这样改有没有问题了:

synchronized public void run() {

------解决方案--------------------
这篇文章或许能解释 http://zhidao.baidu.com/question/224640172.html
------解决方案--------------------
当然不会有,你是对impl实例起了两个线程在跑,这个时候count是共享的。也就是说你把count++交给两个线程去做了,当然不会有200000次啊。

------解决方案--------------------
每次执行的输出好像不能确定吧 。。

------解决方案--------------------
楼主,我考虑了一下,应该会存在这种概率
for(int i=0;i<100000;i++){//打个比方,当i等于100时,这个条件两个线程是不是可以同时满足?
线程1比较积极,先执行了i++语句。变成101。线程2开了个小差,又执行了一把i++。这无形中就少了一次循环
 count++;
 System.out.println(Thread.currentThread().getName()+":"+count);
 }

------解决方案--------------------
因为count为RunnableImpl类的成员变量(类变量),线程t1和t2使用的是同一个RunnableImpl类的实例impl,所以内存中只有一个count变量的拷贝,那线程t1和t2就有可能同时在对count进行读写操作,互相把对方的值给冲掉了,所以有可能你跑10次,10次的count的结果都不一样,但是都是小于20000的值,在线程中对这种只有一个内存拷贝的变量进行操作时可以使用synchronized块来解决共享冲突问题,你试一下这样,得到的结果应该就是20000了,当线程t1和t2的其中一个进入synchronized块后,另外一个线程会在外面等待,直到之前进入的那个线程出来后才会进去,这样就会有一个读写count的先后次序,不会发成冲突了:

for(int i=0;i<100000;i++){

synchronized(count) {
count++;
System.out.println(Thread.currentThread().getName()+":"+count);
}
}


------解决方案--------------------
使用java.util.concurrent.atomic.AtomicInteger :

Java code

// ...
// int count=0;
AtomicInteger count = new AtomicInteger(0);
// ...
// count++;
count.getAndIncrement();
// System.out.println(Thread.currentThread().getName()+":"+count);
System.out.println(Thread.currentThread().getName()+":"+count.get());

------解决方案--------------------
我把楼主的代码复制下来运行了两次
结果最后都是20w
------解决方案--------------------
run 方法里加同步
因为两个线程在操作同一个变量啊
------解决方案--------------------
探讨

引用:
多个进程同时访问一个公共资源,可能会造成公共资源破坏
在某一时刻,两个进程同时对count加一,加之前count假设是20,加一之后就是21
本该是22的,但是结果就是21,以后也有可能发生类似事件,所以造成结果不是200000,而且结果肯定不大于200000


不是说cpu对线程的调度遵循时间片轮转原则,在某一时刻只是一个线程在运行吗?那怎么会出现两个线……

------解决方案--------------------