比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
来源:互联网 发布:纽约大学商学院知乎 编辑:程序博客网 时间:2024/05/17 10:42
比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
得出结论:
(1)使用Lock的性能比使用synchronized关键字要提高4~5倍;
(2)使用信号量实现同步的速度大约比synchronized要慢10~20%;
(3)使用atomic包的AtomicInter速度是比Lock要快1一个数量级。
synchronized:
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。
ReentrantLock:
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。
Atomic:
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。
ReentrantLock 类
java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。ReentrantLock类实现了 Lock,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)
reentrant 锁意味着什么呢?简单来说,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放。这模仿了 synchronized的语义;如果线程进入由线程已经拥有的监控器保护的 synchronized块,就允许线程继续进行,当线程退出第二个(或者后续)synchronized 块的时候,不释放锁,只有线程退出它进入的监控器保护的第一个 synchronized块时,才释放锁。
在查看清单 1 中的代码示例时,可以看到 Lock 和 synchronized 有一点明显的区别 —— lock 必须在 finally 块中释放。否则,如果受保护的代码将抛出异常,锁就有可能永远得不到释放!这一点区别看起来可能没什么,但是实际上,它极为重要。忘记在 finally 块中释放锁,可能会在程序中留下一个定时bomb,当有一天bomb爆炸时,您要花费很大力气才有找到源头在哪。而使用同步,JVM 将确保锁会获得自动释放。
public abstract class Test {
protected String id;
protectedCyclicBarrier barrier;
protected longcount;
protected intthreadNum;
protectedExecutorService executor;
public Test(Stringid, CyclicBarrier barrier, long count, int threadNum,
ExecutorServiceexecutor) {
this.id =id;
this.barrier= barrier;
this.count= count;
this.threadNum= threadNum;
this.executor= executor;
}
public voidstartTest() {
long start= System.currentTimeMillis();
for (int j= 0; j < threadNum; j++) {
executor.execute(newThread() {
@Override
publicvoid run() {
for(int i = 0; i < count; i++) {
test();
}
try{
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
}catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
}
try {
barrier.await();
} catch(InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierExceptione) {
e.printStackTrace();
}
// 所有线程执行完成之后,才会跑到这一步
longduration = System.currentTimeMillis() - start;
System.out.println(id+ " = " + duration);
}
protected abstractvoid test();
}
测试类ReentreLockTest 源码
import thread.test.Test;
public class ReentreLockTest {
private static longCOUNT = 1000000;
private static Locklock = new ReentrantLock();
private static longlockCounter = 0;
private static longsyncCounter = 0;
private static longsemaCounter = 0;
private staticAtomicLong atomicCounter = new AtomicLong(0);
private staticObject syncLock = new Object();
private staticSemaphore mutex = new Semaphore(1);
public static voidtestLock(int num, int threadCount) {
}
static longgetLock() {
lock.lock();
try {
returnlockCounter;
} finally{
lock.unlock();
}
}
static longgetSync() {
synchronized(syncLock) {
returnsyncCounter;
}
}
static longgetAtom() {
returnatomicCounter.get();
}
static longgetSemaphore() throws InterruptedException {
mutex.acquire();
try {
returnsemaCounter;
} finally{
mutex.release();
}
}
static longgetLockInc() {
lock.lock();
try {
return++lockCounter;
} finally{
lock.unlock();
}
}
static longgetSyncInc() {
synchronized(syncLock) {
return++syncCounter;
}
}
static longgetAtomInc() {
returnatomicCounter.getAndIncrement();
}
static classSemaTest extends Test {
publicSemaTest(String id, CyclicBarrier barrier, long count,
intthreadNum, ExecutorService executor) {
super(id,barrier, count, threadNum, executor);
}
@Override
protectedvoid test() {
try{
getSemaphore();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static classLockTest extends Test {
public LockTest(Stringid, CyclicBarrier barrier, long count,
intthreadNum, ExecutorService executor) {
super(id,barrier, count, threadNum, executor);
}
@Override
protectedvoid test() {
getLock();
}
}
static classSyncTest extends Test {
publicSyncTest(String id, CyclicBarrier barrier, long count,
intthreadNum, ExecutorService executor) {
super(id,barrier, count, threadNum, executor);
}
@Override
protectedvoid test() {
getSync();
}
}
static classAtomicTest extends Test {
publicAtomicTest(String id, CyclicBarrier barrier, long count,
intthreadNum, ExecutorService executor) {
super(id,barrier, count, threadNum, executor);
}
@Override
protectedvoid test() {
getAtom();
}
}
public static void test(Stringid, long count, int threadNum,
ExecutorServiceexecutor) {
finalCyclicBarrier barrier = new CyclicBarrier(threadNum + 1,
newThread() {
@Override
publicvoid run() {
}
});
System.out.println("==============================");
System.out.println("count= " + count + "/t" + "Thread Count = "
+threadNum);
newLockTest("Lock ", barrier, COUNT, threadNum, executor).startTest();
newSyncTest("Sync ", barrier, COUNT, threadNum, executor).startTest();
newAtomicTest("Atom ", barrier, COUNT, threadNum, executor)
.startTest();
newSemaTest("Sema ", barrier, COUNT, threadNum, executor)
.startTest();
System.out.println("==============================");
}
public static voidmain(String[] args) {
for (int i= 1; i < 5; i++) {
ExecutorServiceexecutor = Executors.newFixedThreadPool(10 * i);
test("",COUNT * i, 10 * i, executor);
}
}
}
结果
==============================
count = 1000000 ThreadCount = 10
Lock = 953
Sync = 3781
Atom = 78
Sema = 4922
==============================
==============================
count = 2000000 ThreadCount = 20
Lock = 1906
Sync = 8469
Atom = 172
Sema = 9719
==============================
==============================
count = 3000000 ThreadCount = 30
Lock = 2890
Sync = 12641
Atom = 219
Sema = 15015
==============================
==============================
count = 4000000 ThreadCount = 40
Lock = 3844
Sync = 17141
Atom = 343
Sema = 19782
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 voidtest(int round,int threadNum,CyclicBarrier cyclicBarrier){
newSyncTest("Sync",round,threadNum,cyclicBarrier).testTime();
newLockTest("Lock",round,threadNum,cyclicBarrier).testTime();
newAtomicTest("Atom",round,threadNum,cyclicBarrier).testTime();
}
public static voidmain(String args[]){
for(inti=0;i<5;i++){
intround=100000*(i+1);
intthreadNum=5*(i+1);
CyclicBarriercb=new CyclicBarrier(threadNum*2+1);
out.println("==========================");
out.println("round:"+round+"thread:"+threadNum);
test(round,threadNum,cb);
}
}
}
class SyncTest extends TestTemplate{
publicSyncTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super(_id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
synchronizedlong getValue() {
returnsuper.countValue;
}
@Override
synchronizedvoid sumValue() {
super.countValue+=preInit[index++%round];
}
}
class LockTest extends TestTemplate{
ReentrantLocklock=new ReentrantLock();
publicLockTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super(_id, _round, _threadNum, _cb);
}
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
@Override
long getValue() {
try{
lock.lock();
returnsuper.countValue;
}finally{
lock.unlock();
}
}
@Override
void sumValue() {
try{
lock.lock();
super.countValue+=preInit[index++%round];
}finally{
lock.unlock();
}
}
}
class AtomicTest extends TestTemplate{
publicAtomicTest(String _id,int _round,int _threadNum,CyclicBarrier _cb){
super(_id, _round, _threadNum, _cb);
}
@Override
/**
* synchronized关键字不在方法签名里面,所以不涉及重载问题
*/
long getValue() {
returnsuper.countValueAtmoic.get();
}
@Override
void sumValue() {
super.countValueAtmoic.addAndGet(super.preInit[indexAtomic.get()%round]);
}
}
abstract class TestTemplate{
private String id;
protected int round;
private intthreadNum;
protected longcountValue;
protected AtomicLongcountValueAtmoic=new AtomicLong(0);
protected int[]preInit;
protected int index;
protectedAtomicInteger indexAtomic=new AtomicInteger(0);
Random r=newRandom(47);
//任务栅栏,同批任务,先到达wait的任务挂起,一直等到全部任务到达制定的wait地点后,才能全部唤醒,继续执行
privateCyclicBarrier cb;
publicTestTemplate(String _id,int _round,int _threadNum,CyclicBarrier _cb){
this.id=_id;
this.round=_round;
this.threadNum=_threadNum;
cb=_cb;
preInit=newint[round];
for(inti=0;i<preInit.length;i++){
preInit[i]=r.nextInt(100);
}
}
abstract voidsumValue();
/*
* 对long的操作是非原子的,原子操作只针对32位
* long是64位,底层操作的时候分2个32位读写,因此不是线程安全
*/
abstract long getValue();
public voidtestTime(){
ExecutorServicese=Executors.newCachedThreadPool();
longstart=System.nanoTime();
//同时开启2*ThreadNum个数的读写线程
for(inti=0;i<threadNum;i++){
se.execute(newRunnable(){
publicvoid run() {
for(inti=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(newRunnable(){
publicvoid 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();
}
//所有线程执行完成之后,才会跑到这一步
longduration=System.nanoTime()-start;
out.println(id+"= "+duration);
}
}
- 比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
- 比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
- ReentrantLock和synchronized比较
- synchronized和reentrantlock比较
- ReentrantLock和synchronized同步的概述
- ReentrantLock和synchronized的性能对比
- 同步方法ReentrantLock和Synchronized
- 比较 ReentrantLock 和 synchronized 的使用和可伸缩性
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 线程同步方法、性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- 各种同步方法性能比较(synchronized ReentrantLock Atomic)
- 各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
- java同步中的ReentrantLock和synchronized
- Hack方法(持续更新)
- Dropdownlist绑定数据源之后,如何设置期中一个项目为已选项
- usaco--job
- 有10个学生,每个学生的数据包括学号,姓名,3门课的成绩。对其进行处理
- XHTML、CSS与javascript入门经典_第六章 框架
- 比较ReentrantLock和synchronized和信号量Semaphore实现的同步性能
- View类详解(自定义view二)
- Error 1 Inconsistent accessibility: parameter type C#编译时候出错
- 完成设计过程
- 操作系统九虚拟内存
- struts2文件上传的采用的三种方式解析
- windows下使用ssh认证连接git服务器
- install windows8 12.04 on macbook pro md101 2012-7 version
- 使用beanUtils操作属性