zoukankan      html  css  js  c++  java
  • count++线程安全与 synchronized对性能影响的测试

    一个计时器,同时开启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)。

  • 相关阅读:
    transient关键字详解
    大话设计模式之装饰模式
    springboot读取properties(yml)的几种常用方式
    springboot整合druid数据库连接池并开启监控
    初学js的穷举思想
    循环语句
    条件分支语句
    运算符
    案例(-)
    seo搜索引擎优化
  • 原文地址:https://www.cnblogs.com/shixm/p/5490026.html
Copyright © 2011-2022 走看看