synchronized与lock,哪个效率更高

Java在一开始就提供了synchronized关键字,用于多线程之间的同步。它使用简便,不会出现拿锁之后不归还的情况,可以避免一些编程错误。

而jdk5时提供的concurrent包里,有一个Lock接口以及它的实现类:ReentrantLock。这个类提供了更灵活的控制以及更强大的功能。

如果单从性能方面考虑,两个哪个更高效呢?

首先是单线程的加锁情况,见以下代码:

import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock;

public class SynLockTest {

public static void main(String[] args) { 
        long value = 0; 
        int MAX = 10000000; 
        Lock lock = new ReentrantLock(); 
        long start = System.nanoTime(); 
        for (int i = 0; i < MAX; i++) { 
            synchronized (new Object()) { 
                value = value + 1; 
            } 
        } 
        long end = System.nanoTime(); 
        System.out.println("synchronized cost: " + (end – start)/1000000 + "ms");

start = System.nanoTime(); 
        for (int i = 0; i < MAX; i++) { 
            lock.lock(); 
            try { 
                value = value + 1; 
            } finally { 
                lock.unlock(); 
            } 
        } 
        end = System.nanoTime(); 
        System.out.println("lock cost: " + (end – start) + "ns"); 
    } 
}

结果如下:

synchronized cost: 405ms 
lock cost: 479ms

可见Lock的运行时间比synchronized略大。可以推测java编译器为synchronized做了特别优化。

再考虑多线程情况:

public class SynLockTest {

static class SynRunner implements Runnable { 
        private long v = 0;

@Override 
        public synchronized void run() { 
            v = v + 1; 
        } 
    }

static class LockRunner implements Runnable { 
        private ReentrantLock lock = new ReentrantLock(); 
        private long v = 0;

@Override 
        public void run() { 
            lock.lock(); 
            try { 
                v = v + 1; 
            } finally { 
                lock.unlock(); 
            } 
        }

}

static class Tester { 
        private AtomicLong runCount = new AtomicLong(0); 
        private AtomicLong start = new AtomicLong(); 
        private AtomicLong end = new AtomicLong();

public Tester(final Runnable runner, int threadCount) { 
            final ExecutorService pool = Executors.newFixedThreadPool(threadCount); 
            Runnable task = new Runnable() { 
                @Override 
                public void run() { 
                    while (true) { 
                        runner.run(); 
                        long count = runCount.incrementAndGet(); 
                        if (count == 1) { 
                            start.set(System.nanoTime()); 
                        } else if (count >= 10000000) { 
                            if (count == 10000000) { 
                                end.set(System.nanoTime()); 
                                System.out.println(runner.getClass().getSimpleName() + ", cost: " 
                                        + (end.longValue() – start.longValue())/1000000 + "ms");                            } 
                                pool.shutdown(); 
                            return; 
                        } 
                    } 
                } 
            }; 
            for (int i = 0; i < threadCount; i++) { 
                pool.submit(task); 
            } 
        } 
    }

public static void main(String[] args) { 
        new Tester(new SynRunner(), 1); 
        new Tester(new LockRunner(), 1); 
    }

}

现在测试不同线程下的表现(时间单位ms):

  1 10 50 100 500 1000 5000
synchronized 542 4894 4667 4700 5151 5156 5178
lock 838 1211 821 847 851 1211 1241

可以看到,在多线程环境并存在大量竞争的情况下,synchronized的用时迅速上升,而lock却依然保存不变或增加很少。

Lock是用CAS来实现的
JDK 1.6以上synchronized也改用CAS来实现了,所以两者性能差不多
Lock提供的功能丰富点,synchronized的使用简单点

时间: 2024-10-02 05:11:11

synchronized与lock,哪个效率更高的相关文章

.NET快速信息化系统开发框架 V3.2-&gt;WinForm版本新增新的角色授权管理界面效率更高、更规范

角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能)权限.可以对所有角色.用户.模块(菜单).操作(功能)权限进行集中批量设置,角色户授权范围的设置(类似于用户授权范围的设置),表字段权限的设置以及表约束条件权限的设置等. 在角色授权管理模块可以对指定角色进行相应权限的分配与收回,添加与移除角色所拥有的用户,对角色所拥有的操作功能.模块访问权限等进行

浅析PHP的静态成员函数效率更高原因所在

php类的静态成员函数效率比类的普通成员函数的要高. 例子: <?php // php静态方法测试 header('Content-Type: text/html; charset=utf-8'); class xclass{ public static $var1 = '1111111111111111'; public $var2 = 'aaaaaaaaaaaaa'; public function __construct() { $this -> var2 = 'bbbbbbbbbbbb

一种效率更高的for循环

var i,array=[]; for(i=array.length;i--;) { //处理代码 } 1.for循环中使用更少的变量 2.逐步减至0,这样会更快,因为同0比较比同数组的长度比较,或同非0数组比较更有效率. 一种效率更高的for循环

Spring AOP中的JDK和CGLib动态代理哪个效率更高?

一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理,另一种是CGLib的方式. 自Java 1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,后来这项技术被用到了Spring的很多地方. JDK动态代理主要涉及java.lang.reflect包下边的两个类:Proxy和InvocationHandler.其中,Invoc

Python实用技巧:比普通的赋值方式效率更高的二元赋值

python支持类似于a += 3这种二元表达式.比如: 1 a += 3 -> a = a + 3 2 a -= 3 -> a = a - 3 3 a *= 3 -> a = a * 3 4 ... 在python中的某些情况下,这种二元赋值表达式可能比普通的赋值方式效率更高些.原因有二: 二元赋值表达式中,a可能会是一个表达式,它只需计算评估一次,而a = a + 3中,a要计算两次. 对于可变对象,可以直接在原处修改得到修改后的值,而普通的一元赋值表达式必须在内存中新创建一个修改后

Java新手学习路线,0基础学习Java怎样效率更高?

Java是老牌编程语言,拥有扎实的群众基础和广阔的市场应用,从业人员薪资也普遍较高.很多人想要加入到Java开发行列,不过0基础学习Java怎样效率更高? 很多0基础学习Java的同学想知道怎样学习效率更高?小编以为,学习Java需要一个系统的过程,而根据你未来的职位方向不同,学习也各有侧重.目前来说,Java就业方向包括Web开发.大数据开发.Android开发以及各种后端服务开发领域,但不论你选择哪一个,都要从最基础的知识点学习. Java基础知识点多且杂,初学者在开始的时候需要认识什么是J

ConcurrentHashMap多线程下比HashTable效率更高

HashTable使用一把锁处理并发问题,当有多个线程访问时,需要多个线程竞争一把锁,导致阻塞 ConcurrentHashMap则使用分段,相当于把一个HashMap分成多个,然后每个部分分配一把锁,这样就可以支持多线程访问 术语定义 术语 英文 解释 哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值.  哈希表 hash table 根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字在地

WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式,效率更高,灵活性更强)

Q:wm_paint消息在窗口重绘的时候产生,那什么时候窗口会重绘?? A: 严格地说,只有当收到WM_PAINT消息后窗口会重绘 但是引起这个消息的事件有很多, 比如: 首次创建 移动 改变大小 showwindow/ activate window/ invalidate window .... 系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地

Hashtable Dictionary List 谁效率更高

一 前言 很少接触HashTable晚上回来简单看了看,然后做一些增加和移除的操作,就想和List 与 Dictionary比较下存数据与取数据的差距,然后便有了如下的一此测试, 当然我测的方法可能不是很科学,但至少是我现在觉得比较靠谱的方法.如果朋友们有什么好的方法,欢迎提出大家来交流下. 先来简单介绍这三个容器的各自特点吧  1 hashtable 散列表(也叫哈希表),是根据关键字(Key value)而直接访问在内存存储位置的数据结构. 2 List<T> 是针对特定类型.任意长度的一