public class Demo10 {
public static void main(String[] args) {
Thread10 t10 = new Thread10();
for(int i = 0;i<10000;i++) {
Thread t = new Thread(t10);
t.start();
}
}
}
class Thread10 implements Runnable {
private static int count = 0;
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(count++);
}
}
这样有没有可能会出现2个重复的数字??我运行了一下感觉没有,但是我觉得应该会有几率重复的吧?
求大神解释一下,最好讲的明白一点。
如果你在读取和写入中间加一个等待,那么,这个是肯定会有重复的,也就是说
system.out.println(count);
wait(1000);
count++;
这个重复就会很明显
这个你可以从内存的角度来考虑,你在内存里面申请了一段公共空间,你每次只是执行读取内存,然后再写入内存,虽然是多线程,但是对于同一个地址的内存是不会同时给两个线程同时读取,加上你读取和写入的时间非常短,所以这个概率基本是不存在的!
count++是速度很快,只是变换寄存器里的位,比System.out.println等函数快不是一个级别
计算机内存中最快的是寄存器,直接和cpu交互,count++底层是改变寄存器中0->1,1->0实现变量的自增,速度不是一般的快,第一个线程system.out
之后,count就瞬间自增完了,下一个线程输出时就是自增自后的count
count++ 看上去好像是原子性的操作,但实际上在程序中最起码有三步 1:从内存把count读取到寄存器中 2:在寄存器上运算+1 3:把运算之后的结果
存储到内存上。所以如果有两个线程在执行count++时,(假设此时count=1),线程1执行步骤2,还没有执行步骤3,那么内存中的count还是1;
此时线程执行步骤1,那么读取的count值还是1,不是2,那么就会出现两个线程打印一样的数字了
你的count++会跳越,比如说你设置上限是20,假如有10个线程,可能同时访问到20,那么进行++操作,就有可能变为30,假如有100万并发量,那么损失将是无法计算的,曾经淘宝就在并发量上吃了一次亏,所以对于多线程操作,就要用多线程的变量,不要用普通变量,就比说int,那么java中对应有AotmicInteger的类,是线程安全的,就不存在两个线程拿到统一个数据的情况,jdk有个current的包,那个包下面全是线程并发相关的,多看看,dueg lea先生写的,最好买本将线程并发的书,不要买中文的,买英文的.ok!欢迎关注!
楼主的意思是:线程的运行是异步的,会不会出现一个线程在前一个线程还没有对count完成++之前对它进行++命令,导致两个线程的结果一样?
这种情况是不会发生的:楼上的所说的速度问题,其实就算速度不快也不会发生,static 变量 count 申请的内存地址在所有线程执行时都不会改变,
意味着对同一个内存地址的内容做修改绝对不会同时发生,只要有先后就会一直累加上去
纠正:通过测试发现
public class StaticTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
CountThread mThread = new CountThread();
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(mThread);
thread.start();
}
}
}
class CountThread implements Runnable {
private static int count = 0;
public void run() {
try {
Thread.sleep(1000);
System.out.println("count : " + count++);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
结果中有:
count : 47
count : 47
出现了重复,原因在查找中...
让我想起了我当初刚学java时候,期末考试题,火车订票系统。。。。