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的使用简单点

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

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

    角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能) ...

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

    角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能) ...

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

    一.背景 今天有小伙伴面试的时候被问到:Spring AOP中JDK 和 CGLib动态代理哪个效率更高? 二.基本概念 首先,我们知道Spring AOP的底层实现有两种方式:一种是JDK动态代理, ...

  4. MySQL select * 和把所有的字段都列出来,哪个效率更高?

    MySQL select * 和把所有的字段都列出来,哪个效率更高 答案是:如何,都不推荐使用 SELECT * FROM (1)SELECT *,需要数据库先 Query Table Metadat ...

  5. Http请求封装(对HttpClient类的进一步封装,使之调用更方便。另外,此类管理唯一的HttpClient对象,支持线程池调用,效率更高)

    package com.ad.ssp.engine.common; import java.io.IOException; import java.util.ArrayList; import jav ...

  6. 在类中,调用这个类时,用$this->video_model是不是比每次调用这个类时D('Video')效率更高呢

    在类中,调用这个类时,用$this->video_model是不是比每次调用这个类时D('Video')效率更高呢  

  7. 取代 Mybatis Generator,这款代码生成神器配置更简单,开发效率更高!

    作为一名 Java 后端开发,日常工作中免不了要生成数据库表对应的持久化对象 PO,操作数据库的接口 DAO,以及 CRUD 的 XML,也就是 mapper. Mybatis Generator 是 ...

  8. 数据库查询SQL语句的时候如何写会效率更高?

    引言 以前刚开始做项目的时候,开发经验尚浅,遇到问题需求只要把结果查询出来就行,至于查询的效率可能就没有太多考虑,数据少的时候还好,数据一多,效率问题就显现出来了.每次遇到查询比较慢时,项目经理就会问 ...

  9. Java分布式唯一ID生成方案——比UUID效率更高的生成id工具类

    package com.xinyartech.erp.core.util; import java.lang.management.ManagementFactory; import java.net ...

  10. i++与++i哪个效率更高

    简单的比较前缀自增运算符和后缀自增运算符的效率是片面的, 因为存在很多因素影响这个问题的答案. 首先考虑内建数据类型的情况: 如果自增运算表达式的结果没有被使用, 而是仅仅简单地用于增加一元操作数, ...

随机推荐

  1. Asp.net MVC NPOI导出Excel

    public class NpoiMemoryStream : MemoryStream { public NpoiMemoryStream() { AllowClose = true; } publ ...

  2. Web前端开发最佳实践(11):使用更严格的JavaScript编码方式,提高代码质量

    前言 JavaScript语言由于其固有的灵活性,所以导致开发者可以写出很多诡异的代码,甚至一些较为正常的特性,如类型隐式转换.this的指代等等,也会让刚接触此语言的开发者头大不已.尤其是那些熟知其 ...

  3. 【LOJ】#2587. 「APIO2018」铁人两项

    题解 学习了圆方树!(其实是复习了Tarjan求点双) 我又双叒叕忘记了tarjan点双一个最重要,最重要的事情! 就是--假如low[v] >= dfn[u],我们就找到了一个点双,开始建立方 ...

  4. USACO 6.2 Calf Flac

    Calf Flac It is said that if you give an infinite number of cows an infinite number of heavy-duty la ...

  5. codeforces 286 E. Ladies' Shop (FFT)

    E. Ladies' Shop time limit per test 8 seconds memory limit per test 256 megabytes input standard inp ...

  6. 编写一个简单的 JDBC 程序

    连接数据库的步骤: 1.注册驱动(只做一次) 2.建立连接(Connection) 3.创建执行SQL的语句(Statement) 4.执行语句 5.处理执行结果(ResultSet) 6.释放资源 ...

  7. 【工具】获取pojo类属性,并写入表格

    1.添加依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <g ...

  8. @ControllerAdvice + @ExceptionHandler 处理 全部Controller层异常

    对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来, ...

  9. mysql索引之三:索引使用注意规则(索引失效--存在索引但不使用索引)*

    使用索引时,有以下一些技巧和注意事项: (1)越小的数据类型通常更好:越小的数据类型通常在磁盘.内存和CPU缓存中都需要更少的空间,处理起来更快.(2)简单的数据类型更好:整型数据比起字符,处理开销更 ...

  10. MySQL Insert语句单个批次数量过多导致的CPU性能问题分析

    [问题] 最近有台服务器比较频繁的CPU报警,表现的特征有CPU sys占比偏高,大量慢查询,大量并发线程堆积.后面开发对insert的相关业务限流后,服务器性能恢复正常. [异常期间线程处理情况] ...