java 线程安全问题疑惑求解?

Line 发布于 2013/04/16 15:55
阅读 267
收藏 0
本来想验证一些线程不安全的问题,又看到说i++不是一个原子操作,猜想如果我用一些线程执行i++,j++操作,另一些线程执行i,和j 的输出,那么如果开始i 和 j 相等的话,有可能出现不相等的情况。 编写了代码测试,发觉效果看不出来,求指导一下。初学者,先谢谢了。
package shape;

public class Try {


     static int i = 0,j = 0;
     static void add(){
         i++;
         j++;
     }
     static void put(){
         System.out.println("i = " + i + " j = " + j);
     }
     public static void main(String arg[]){
        for(int i = 0 ; i < 10000; i++){
            new Thread(){
             @Override
             public void run(){
                  Try.put();
             }
            }.start();
            new Thread(){
             @Override
             public void run(){
                  Try.add();
             }
         }.start();
        }
     }
}

加载中
0
xiaoxia
xiaoxia

你的写法有很大的问题,首先你for循环10000次每次起一个add线程 运行一次然后立马关掉,这样是很难找出问题的。我改了一下你的代码,你自己看,不想解释。

public class Test {
	static int i = 0, j = 0;
	static void add() {
		i++;
		j++;
	}
	static boolean put() {
		if (i != j) {
			System.out.println(Thread.currentThread().getName() + "  i = " + i + " j = " + j);
			return false;
		}
		return true;
	}
	public static void main(String arg[]) {
		for (int i = 0; i < 6; i++) {
			new Thread(new Runnable() {
				public void run() {
					for (int i = 0; i < 100000; i++) {//如果没效果可以调大此数字,或者多运行几次程序,应为出现线程不同步是有很大随机性的。
						Test.add();
						if (!Test.put()) {
							return;
						}
					}
				}
			}).start();
		}
	}
}

Line
Line
想了一下,确实按我那样写线程竞争不明显。我试了你这样,出了一句很有代表的数据,打印出了相等的i 和 j 。 在判断的时候还是不相等的,输出的时候就相等了。
0
夏文雄
夏文雄

根本就没用到线程啊。必须继承Thread类,实现Runnable接口

0
三毛々
三毛々

引用来自“夏文雄”的答案

根本就没用到线程啊。必须继承Thread类,实现Runnable接口

new Thread(){
             @Override
             public void run(){
                  Try.put();
             }
            }.start();
这里用的不就是线程吗???




0
三毛々
三毛々

i = 9954 j = 9957
i = 9955 j = 9958
i = 9956 j = 9959
i = 9957 j = 9960
i = 9958 j = 9961
i = 9959 j = 9962
i = 9960 j = 9963
i = 9961 j = 9964
i = 9962 j = 9965
i = 9964 j = 9967
i = 9964 j = 9967
i = 9965 j = 9968
i = 9966 j = 9969
i = 9968 j = 9971
i = 9967 j = 9970
i = 9970 j = 9973
i = 9971 j = 9974
i = 9971 j = 9974
i = 9972 j = 9975
i = 9973 j = 9976
i = 9974 j = 9977
i = 9975 j = 9978
i = 9976 j = 9979
i = 9977 j = 9980
i = 9978 j = 9981
i = 9979 j = 9982
i = 9981 j = 9984
i = 9982 j = 9985
i = 9982 j = 9985
i = 9983 j = 9986
i = 9984 j = 9987
i = 9985 j = 9988
i = 9986 j = 9989
i = 9987 j = 9990
i = 9988 j = 9991
i = 9989 j = 9992
i = 9990 j = 9993
i = 9991 j = 9994
i = 9992 j = 9995
i = 9993 j = 9996
i = 9994 j = 9997
这是我跑出来的最后结果。

i++是不是原子操作我不清楚。这里的代码应该很容易就会出现i和j不等的情况啊。





Line
Line
我囧了,我自己跑了N次都是相同的。
0
huan
huan
i++ 会被编译为三条机器操作码。这里才两个线程,竞争不激烈,多开些线程跑会更明显些。
0
Line
Line

引用来自“huan”的答案

i++ 会被编译为三条机器操作码。这里才两个线程,竞争不激烈,多开些线程跑会更明显些。
每一个for 不就多开了一个线程,我想应该是每个线程的执行时间太短,执行的时间也就2个i++的时间。又因为一个for循序执行完线程语句也要一次计数变量的自加以及布尔判断,时间差不多,所以就显示不出效果来了。
返回顶部
顶部