各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的情形下做出正确的选择。
总体的结论先摆出来:
synchronized:
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。
ReentrantLock:
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。
Atomic:
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。
所以,我们写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。
先贴测试结果:再贴代码(Atomic测试代码不准确,一个同步中只能有1个Actomic,这里用了2个,但是这里的测试只看速度)
==========================
round:100000 thread:5
Sync = 35301694
Lock = 56255753
Atom = 43467535
==========================
round:200000 thread:10
Sync = 110514604
Lock = 204235455
Atom = 170535361
==========================
round:300000 thread:15
Sync = 253123791
Lock = 448577123
Atom = 362797227
==========================
round:400000 thread:20
Sync = 16562148262
Lock = 846454786
Atom = 667947183
==========================
round:500000 thread:25
Sync = 26932301731
Lock = 1273354016
Atom = 982564544
Java代码
package test.thread; import static java.lang.System.out; import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock; public class TestSyncMethods { public static void test(int round,int threadNum,CyclicBarrier cyclicBarrier){
new SyncTest("Sync",round,threadNum,cyclicBarrier).testTime();
new LockTest("Lock",round,threadNum,cyclicBarrier).testTime();
new AtomicTest("Atom",round,threadNum,cyclicBarrier).testTime();
} public static void main(String args[]){ for(int i=0;i<5;i++){
int round=100000*(i+1);
int threadNum=5*(i+1);
CyclicBarrier cb=new CyclicBarrier(threadNum*2+1);
out.println("==========================");
out.println("round:"+round+" thread:"+threadNum);
test(round,threadNum,cb); }
}
} class SyncTest extends TestTemplate{
public SyncTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super( _id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
synchronized long getValue() {
return super.countValue;
}
@Override
synchronized void sumValue() {
super.countValue+=preInit[index++%round];
}
} class LockTest extends TestTemplate{
ReentrantLock lock=new ReentrantLock();
public LockTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super( _id, _round, _threadNum, _cb);
}
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
@Override
long getValue() {
try{
lock.lock();
return super.countValue;
}finally{
lock.unlock();
}
}
@Override
void sumValue() {
try{
lock.lock();
super.countValue+=preInit[index++%round];
}finally{
lock.unlock();
}
}
} class AtomicTest extends TestTemplate{
public AtomicTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super( _id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
long getValue() {
return super.countValueAtmoic.get();
}
@Override
void sumValue() {
super.countValueAtmoic.addAndGet(super.preInit[indexAtomic.get()%round]);
}
}
abstract class TestTemplate{
private String id;
protected int round;
private int threadNum;
protected long countValue;
protected AtomicLong countValueAtmoic=new AtomicLong(0);
protected int[] preInit;
protected int index;
protected AtomicInteger indexAtomic=new AtomicInteger(0);
Random r=new Random(47);
//任务栅栏,同批任务,先到达wait的任务挂起,一直等到全部任务到达制定的wait地点后,才能全部唤醒,继续执行
private CyclicBarrier cb;
public TestTemplate(String _id,int _round,int _threadNum,CyclicBarrier _cb){
this.id=_id;
this.round=_round;
this.threadNum=_threadNum;
cb=_cb;
preInit=new int[round];
for(int i=0;i<preInit.length;i++){
preInit[i]=r.nextInt(100);
}
} abstract void sumValue();
/*
* 对long的操作是非原子的,原子操作只针对32位
* long是64位,底层操作的时候分2个32位读写,因此不是线程安全
*/
abstract long getValue(); public void testTime(){
ExecutorService se=Executors.newCachedThreadPool();
long start=System.nanoTime();
//同时开启2*ThreadNum个数的读写线程
for(int i=0;i<threadNum;i++){
se.execute(new Runnable(){
public void run() {
for(int i=0;i<round;i++){
sumValue();
} //每个线程执行完同步方法后就等待
try {
cb.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
});
se.execute(new Runnable(){
public void run() { getValue();
try {
//每个线程执行完同步方法后就等待
cb.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
});
} try {
//当前统计线程也wait,所以CyclicBarrier的初始值是threadNum*2+1
cb.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BrokenBarrierException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//所有线程执行完成之后,才会跑到这一步
long duration=System.nanoTime()-start;
out.println(id+" = "+duration); } }
各种同步方法性能比较(synchronized,ReentrantLock,Atomic)的更多相关文章
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的.原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不 ...
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...
- 并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲
前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别 ...
- ThreadLocal、Volatile、synchronized、Atomic
前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别 ...
- synchronized,ReentrantLock解决锁冲突,脏读的问题
最常见的秒杀系统,解决思路就是从前端.后台服务.数据库层层去掉负载,以达到平衡 锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLo ...
- synchronized ReentrantLock 比较分析
在编写多线程代码的时候,对于不允许并发的代码,很多需要加锁进行处理.在进行加锁处理时候,synchronized作为java的内置锁,同时也是java关键字,最为被人熟知,即使是最初级的java程序员 ...
- 还在用Synchronized?Atomic你了解不?
前言 只有光头才能变强 之前已经写过多线程相关的文章了,有兴趣的同学可以去了解一下: https://github.com/ZhongFuCheng3y/3y/blob/master/src/thre ...
- Java性能之synchronized锁的优化
synchronized / Lock 1.JDK 1.5之前,Java通过synchronized关键字来实现锁功能 synchronized是JVM实现的内置锁,锁的获取和释放都是由JVM隐式实现 ...
- java 多线程实现四种方式解析Thread,Runnable,Callable,ServiceExcutor,Synchronized ,ReentrantLock
1.Thread实现: import java.util.Date; import java.text.SimpleDateFormat; public class MyThread extends ...
随机推荐
- 在Android开发中使用Ant 一:环境的搭建及入门
配置Ant环境 下载Ant:http://ant.apache.org/bindownload.cgi 在windows上应该选择zip压缩包,将zip压缩包解压到一个目录. 打开系统环境变量,在系统 ...
- MyBatis入门(一)---基本使用
一.MyBatis简介 1.1.概述 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. M ...
- Web应用程序系统的多用户权限控制设计及实现-首页模块【5】
首页模块就是展示不同权限的最终结果了,在阅读这章之前若有些不明白,可看看后续的单独的权限模块,用户模块,目录模块后从整体上再看首页模块. 阅读该模块需要一定或者是比较熟练的js知识,EasyUI Ta ...
- 在iOS 8中使用UIAlertController
iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...
- 怎样在VS2010中打开VS2012的项目
VS2012中对C#的支持度非常好,不管是编写方便程度(不需要插件就能高亮代码及代码自动提示功能),还对MFC的一些功能优化很多. 我们可以修改两个工程文件来把VS2012的工程文件一直到VS2010 ...
- iOS开发者必备的10款工具
当前iOS和Android两大移动操作系统“二足鼎立”,几乎覆盖了市面上大部分的智能手机.相比Android,iOS开发适配更简单,且随着各种实用工具和Swift语言的出现,iOS开发门槛地降低,开发 ...
- JS 日期对象在浏览器间的若干差异
JS中 ,通过 new Date() 可以获取当前时间 也可以通过 new Date("2013/12/12 8:00:00")的方式,创建某个指定时间对象 在Chrome和FF下 ...
- 闭包Closures
所谓闭包,可以理解为一个可以用于函数,参数,返回值处的代码块 import Foundation func isGood(a:Int,b:Int)->Bool{ return a>b; } ...
- 【转】App开发者必备的运营、原型、UI设计工具整理
一.运营类 1. APPVIEW,网址:http://lab.hakim.se/appview/ 帮助iOS 应用开发者追踪所有地区App Store最近的用户评论,可以按时间.评分.地区排序,缺点是 ...
- Redis的数据类型及操作
Strings 最简单的类型,一个Key对应一个Value,string类型是二进制安全的.Redis的string可以包含任何数据,如图片或序列化的对象 操作 Set:设置key对应的值为strin ...