经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
简单测试Java线程安全中阻塞同步与非阻塞同步性能
来源:cnblogs  作者:欲戴王冠.必承其重  时间:2018/10/23 9:28:44  对本文有异议

摘抄自周志明老师的《深入理解Java虚拟机:JVM高级特性与最佳实践》13.2.2 线程安全的实现方法

1.名词解释

同步是指锁哥线程并发访问共享数据时,保证共享数据同一时刻只被一个线程访问

互斥同步(阻塞同步)是一种悲观的并发策略,总是认为只要不去做正确的同步措施(加锁),那就肯定会出现问题。

阻塞同步最主要的问题是进行线程阻塞和唤醒所带来的性能问题,因为在JDK 1.2之后,Java的线程模型被替换为基于操作系统原生线程模型来实现,如要阻塞唤醒一个线程,都需要操作系统来帮忙完成,这就需要用户态转换到内核态,会耗费很多时间。

非阻塞同步:随着硬件指令集的发展,我们有了另一种选择:基于冲突检测的乐观并发策略,这种操作不需要挂起线程,会节省很多时间,比如CAS(compare and swap)指令。

2.开始测试

第一种加锁方式:

  1. static int a=0;
  2. public static void lock() {
  3. Thread[] threads=new Thread[50];
  4. for(int i=0;i<threads.length;i++){
  5. threads[i]=new Thread(new Runnable() {
  6. @Override
  7. public void run() {
  8. for(int i=0;i<100000;i++){
  9. synchronized(Main.class){
  10. a++;
  11. }
  12. }
  13. }
  14. });
  15. threads[i].start();
  16. }
  17. while(Thread.activeCount() > 1){
  18. Thread.yield();
  19. }
  20. System.out.println(a);
  21. }

第二种CAS方式:

  1. static AtomicInteger integer=new AtomicInteger(0);
  2. public static void cas() {
  3. Thread[] threads=new Thread[50];
  4. for(int i=0;i<threads.length;i++){
  5. threads[i]=new Thread(new Runnable() {
  6. @Override
  7. public void run() {
  8. for(int i=0;i<100000;i++){
  9. integer.incrementAndGet();
  10. }
  11. }
  12. });
  13. threads[i].start();
  14. }
  15. while(Thread.activeCount() > 1){
  16. Thread.yield();
  17. }
  18. System.out.println(integer.get());
  19. }

3结论:运行两个方法,同样是50个线程,100000个自增,输出时间差,可以看到性能之间的差异。

lock方法平均在1270ms

cas方法平均在175ms

可以看到阻塞同步与非阻塞同步之间巨大的差异,也可以看出Java线程用户态内核态切换损耗的处理器时间很大。

 

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号