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

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. centos 7.5 安装mongodb

    MongoDB安装和启动 从官网下载最新对应的版本然后解压,本文以3.6.9为例,将文件拷贝到opt目录下,然后解压: [root@localhost opt]# tar zxvf mongodb-l ...

  2. 在线学习和在线凸优化(online learning and online convex optimization)—FTRL算法6

  3. MAN 手册各章节功能介绍及快捷键键位整理

    前言   Man 手册页(Manua pages ,缩写man page) 是在linux操作系统在线软件文档的一种普遍形式.内容包括计算机程序库和系统调用等命令的帮助手册. 手册页是用troff排版 ...

  4. Solr SchemaXml 一些解读

    The schema.xml file contains all of the details about which fields your documents can contain, and h ...

  5. 单例模式(Singleton)

    单例模式  Singletonn Pattern Ensure a class has only one instance, and provide  a global point of access ...

  6. python+selenium+requests爬取我的博客粉丝的名称

    爬取目标 1.本次代码是在python2上运行通过的,python3的最需改2行代码,用到其它python模块 selenium 2.53.6 +firefox 44 BeautifulSoup re ...

  7. TCP keep-alive翻译

    原文链接: http://www.freesoft.org/CIE/RFC/1122/114.htmhttp://www.freesoft.org/CIE/RFC/1122/index.htm 实现T ...

  8. SHOW CREATE语句

    show create table tablename 查看某表的建表语句 同理查看存储过程 show create procedure  sp_name

  9. HTML5 Canvas ( 图形的像素操作 ) getImageData, putImageData, ImgData.data

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. 关联github, 添加gitignore 规则

    1. 新建Maven项目 2. 新建github repository 3. 执行命令 echo "# se" >> README.md git init git ad ...