鴻飛

导航

 

一个计时器,同时开启100个线程,每个线程休眠1ms钟后,将全局静态变量count加1,这100个线程创建完之后,休眠500ms,计算总耗时,程序如下:

public class Counter {

    public volatile static int count = 0;
    public static void inc() {
        // 这里延迟1毫秒,使得结果明显
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }
        count++;
    }
    public static void main(String[] args) {
        long time1 = System.currentTimeMillis();
        System.out.println();
        for (int i = 0; i < 100; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Counter.inc();
                }
            }).start();
        }
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 这里每次运行的值都有可能不同,可能为100
        System.out.println("Counter.count=" + Counter.count);
        long time2 = System.currentTimeMillis();
        System.out.println("耗时:"+(time2-time1));
    }
}

运行结果:

Counter.count=96
耗时:506

Counter.count不等于100是因为count++线程不安全

加上同步代码块:

public class Counter {

	public volatile static int count = 0;
	static Object obj = new Object();
	public static void inc() {
		// 这里延迟1毫秒,使得结果明显
		try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
		}
		synchronized (obj) {
			count++;
		}
	}

	public static void main(String[] args) {
		long time1 = System.currentTimeMillis();
		System.out.println();
		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					Counter.inc();
				}
			}).start();
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 这里每次运行的值都有可能不同,可能为1000
		System.out.println("Counter.count=" + Counter.count);
		long time2 = System.currentTimeMillis();
		System.out.println("耗时:"+(time2-time1));
	}
}

运行结果:

Counter.count=100
耗时:507

那么synchronized对运行的速度有多大的影响,于是我分别100,1000,10000,100000与500000次,将未同步、synchronized (obj)与synchronized (Counter.class)结果对比,结果如下:

 

线程数量 未同步<测试更多的数据> synchronized (obj) synchronized (Counter.class)
100 Counter.count=97
耗时:508
<98-506><98-507><97-507><100-508>
Counter.count=100
耗时:507
<100-507><100-507><100-508><100-508>
Counter.count=100
耗时:506
<100-508><100-508><100-506><100-509>
1000 Counter.count=997
耗时:572
<993-562><994-562><995-561><990-561>
Counter.count=1000
耗时:562
<1000-572><1000-560><1000-559><1000-560>
Counter.count=1000
耗时:570
<1000-585><1000-560><1000-562><1000-561>
10000 Counter.count=9947
耗时:1067
<9951-1077><9962-1079><9936-1066><9953-1081>
Counter.count=10000
耗时:1074
<10000-1075><10000-1068><10000-1079><10000-1074>
Counter.count=10000
耗时:1072
<10000-1089><10000-1076><10000-1108><10000-1076>
100000 Counter.count=99399
耗时:6098
<99347-6111><99374-6099><99416-6196><99459-6137>
Counter.count=100000
耗时:6103
<100000-6101><100000-6104><100000-6155><100000-6107>
Counter.count=100000
耗时:6150
<100000-6287><100000-6182><100000-6159><100000-6104>
500000 Counter.count=497242
耗时:28892
<497394-30674><497274-29864><497129-29470><497216-29529>
Counter.count=500000
耗时:31232
<500000-29297><500000-29053><500000-29166><500000-29006>
Counter.count=500000
耗时:29251
<500000-29743><500000-29334><500000-29600><500000-29848>

 

将上面耗时时间求平均值,得到:

线程数量 未同步平均用时 synchronized (obj)平均用时 synchronized (Counter.class)平均用时
100 507.2 507.4 507.4
1000 563.6 562.6 567.6
10000 1074 1074 1084.2
100000 6128.2 6114 6176.4
500000 29685.8 29550.8 29555.2

于是,得出结论:
1、synchronized可以解决多线程造成的count++不准确的问题。

2、随着线程数量的增加,加过synchronized后的代码,并不会对速度产生很明显的影响。

3、从1万与10万的结果来看,经过synchronized(obj)处理后的程序,要比synchronized(Counter.class)处理后的程序大约要快10ms。而100、1000与50万,synchronized(obj)与synchronized(Counter.class)执行速度几乎相等。从总体来看,随着线程数量的增加,synchronized(Counter.class)执行的效率并没有明显的低于synchronized(obj)。

posted on 2016-05-13 17:55  鴻飛  阅读(1101)  评论(0编辑  收藏  举报