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

  1. public class Counter {
  2.  
  3. public volatile static int count = 0;
  4. public static void inc() {
  5. // 这里延迟1毫秒,使得结果明显
  6. try {
  7. Thread.sleep(1);
  8. } catch (InterruptedException e) {
  9. }
  10. count++;
  11. }
  12. public static void main(String[] args) {
  13. long time1 = System.currentTimeMillis();
  14. System.out.println();
  15. for (int i = 0; i < 100; i++) {
  16. new Thread(new Runnable() {
  17. @Override
  18. public void run() {
  19. Counter.inc();
  20. }
  21. }).start();
  22. }
  23. try {
  24. Thread.sleep(500);
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. // 这里每次运行的值都有可能不同,可能为100
  29. System.out.println("Counter.count=" + Counter.count);
  30. long time2 = System.currentTimeMillis();
  31. System.out.println("耗时:"+(time2-time1));
  32. }
  33. }

运行结果:

Counter.count=96
耗时:506

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

加上同步代码块:

  1. public class Counter {
  2.  
  3. public volatile static int count = 0;
  4. static Object obj = new Object();
  5. public static void inc() {
  6. // 这里延迟1毫秒,使得结果明显
  7. try {
  8. Thread.sleep(1);
  9. } catch (InterruptedException e) {
  10. }
  11. synchronized (obj) {
  12. count++;
  13. }
  14. }
  15.  
  16. public static void main(String[] args) {
  17. long time1 = System.currentTimeMillis();
  18. System.out.println();
  19. for (int i = 0; i < 100; i++) {
  20. new Thread(new Runnable() {
  21. @Override
  22. public void run() {
  23. Counter.inc();
  24. }
  25. }).start();
  26. }
  27. try {
  28. Thread.sleep(500);
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. // 这里每次运行的值都有可能不同,可能为1000
  33. System.out.println("Counter.count=" + Counter.count);
  34. long time2 = System.currentTimeMillis();
  35. System.out.println("耗时:"+(time2-time1));
  36. }
  37. }

运行结果:

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)。

count++线程安全与 synchronized对性能影响的测试的更多相关文章

  1. 关于nagios监控远程服务器对服务器性能影响的测试

    1.    Nagios监视远程服务器时,是通过在控制端执行以下命令进行数据收集的: /usr/local/nagios/libexec/check_http -I 192.168.16.11 /us ...

  2. 线程变量(ThreadLocal)的使用和测试

    ThreadLocal可以定义线程范围的变量,也可以称之为线程局部变量.与一般的变量的区别在于,生命周期是在线程范围内的. 也就是说某个类的某个对象(为清晰描述,以下称A对象)里面有个ThreadLo ...

  3. 线程池 队列 synchronized

    线程池 BlockingQueue synchronized volatile 本章从线程池到阻塞队列BlockingQueue.从BlockingQueue到synchronized 和 volat ...

  4. 从线程池到synchronized关键字详解

    线程池 BlockingQueue synchronized volatile 前段时间看了一篇关于"一名3年工作经验的程序员应该具备的技能"文章,倍受打击.很多熟悉而又陌生的知识 ...

  5. Synchronized锁性能优化偏向锁轻量级锁升级 多线程中篇(五)

    不止一次的提到过,synchronized是Java内置的机制,是JVM层面的,而Lock则是接口,是JDK层面的 尽管最初synchronized的性能效率比较差,但是随着版本的升级,synchro ...

  6. .Net Discovery系列之十二-深入理解平台机制与性能影响(下)

    上一篇文章中Aicken为大家介绍了.Net平台的垃圾回收机制.即时编译机制与其对性能的影响,这一篇中将继续为大家介绍.Net平台的异常捕获机制与字符串驻留机制. 三.关于异常捕获机制 虽然我们已经很 ...

  7. 线程的同步控制synchronized和lock的对比和区别

     转载. https://blog.csdn.net/wu1226419614/article/details/73740899 我们在面试的时候,时常被问到如何保证线程同步已经对共享资源的多线程编程 ...

  8. 线程安全与synchronized

    线程安全性与synchronized 线程安全:多线程访问某个类时,这个类始终都能表现出正确的行为,这个类就是线程安全的. 简单的说,就是多线程执行的结果与单线程执行的结果始终一致,不会因为多线程的执 ...

  9. ToList<>()所带来的性能影响

    ToList<>()所带来的性能影响  前几天优化师弟写的代码,有一个地方给我留下很深刻的印象,就是我发现他总是将PLINQ的结果ToList<>(),然后再返回给主程序,对于 ...

随机推荐

  1. mui plus.uploader.createUpload 上传文件服务端获取文件名中文乱码问题

    客户端上传文件需要做一次url编码:encodeURIComponent(fileName) 服务端:URL解码 var fileName = HttpUtility.UrlDecode(hfc.Fi ...

  2. 如何随机从数据库表中抽一条数据的SQL语句

    NewID() 方法返回一个 GUID,如:EE95A489-B721-4E8A-8171-3CA8CB6AD9E4 在 select 表的时候,再增加一列为 NewID() 就可以了. SQL 语句 ...

  3. C# winfrom ComboBox 调整下拉菜单的高度

    1.设置属性 // 1.属性设置 DrawMode ->OwnerDrawVariable this.cboBoxPostID.DrawMode = System.Windows.Forms.D ...

  4. supervisord管理进程详解

    supervisord管理进程详解 supervisor配置详解(转) 官网 Linux后台进程管理利器:supervisor supervisor使用详解

  5. sklearn中的metrics模块中的Classification metrics

    metrics是sklearn用来做模型评估的重要模块,提供了各种评估度量,现在自己整理如下: 一.通用的用法:Common cases: predefined values 1.1 sklearn官 ...

  6. 在控制终端输入AT命令

    控制台终端输入AT命令到smd8,步骤如下: 1. 先执行命令 cat /dev/smd8 & 2. 再执行  echo  -e  "ati\r\n"  > /dev ...

  7. python protobuf序列化repeated运用

    下面是proto描述文件的定义 message Person { required string name = 1; required int32 id = 2; optional string em ...

  8. javascript创建对象之构造函数模式(二)

    对上一章节的工厂模式进行代码重写 function Human(name, sex) { this.name = name; this.sex = sex; this.say = function ( ...

  9. KuDu论文解读

    kudu是cloudera在2012开始秘密研发的一款介于hdfs和hbase之间的高速分布式存储数据库.兼具了hbase的实时性.hdfs的高吞吐,以及传统数据库的sql支持.作为一款实时.离线之间 ...

  10. 腾讯优图&港科大提出一种基于深度学习的非光流 HDR 成像方法

    目前最好的高动态范围(HDR)成像方法通常是先利用光流将输入图像对齐,随后再合成 HDR 图像.然而由于输入图像存在遮挡和较大运动,这种方法生成的图像仍然有很多缺陷.最近,腾讯优图和香港科技大学的研究 ...