`
houlinyan
  • 浏览: 150053 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

Lock与synchronized 的区别

阅读更多

多次思考过这个问题,都没有形成理论,今天有时间了,我把他总结出来,希望对大家有所帮助

 

 

1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候

     线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,

     如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断

     如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

 

    ReentrantLock获取锁定与三种方式:
    a)  lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

    b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;

    c)tryLock(long timeout,TimeUnit unit),   如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;

    d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

 

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

 

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

 

 

下面内容 是转载 http://zzhonghe.iteye.com/blog/826162

 

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

代码如下:

 

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);   
           
    }   
  
}  

 

分享到:
评论
2 楼 远方_张涛 2016-01-13  
赞一个,写的很好
1 楼 somefuture 2014-04-07  
这个一定要学会的。谢谢。

相关推荐

    信通商务网2025修正版

    中国电子商务平台,打造中国最具影响力的企业电子商务平台,商机信息,产品资料,企业名录,行业展览会,商务新闻。

    经典文学作品阅读体验.doc

    经典文学作品阅读体验

    python-30.判断 2 的幂-反正你没它快.py

    python-30.判断 2 的幂——反正你没它快.py

    基于随机森林实现特征选择降维及回归预测 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    元胞自动机模拟病毒传染(SEIR模型) 附Python代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    2004-2020年各省货运量数据

    2004-2020年各省货运量数据 1、时间:2004-2020年 2、来源:国家统计j、统计nj 3、指标:行政区划代码、地区、年份、货运量(万吨) 4、范围:31省

    ADC推理软件AI程序

    ADC推理软件AI程序

    【轴承故障检测】滚动轴承中进行基于振动的故障诊断研究 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    java-springboot+vue景区民宿预约系统实现源码(完整前后端+mysql+说明文档+LunW+PPT).zip

    java-springboot+vue景区民宿预约系统实现源码(完整前后端+mysql+说明文档+LunW+PPT).zip

    漫画作品与增强现实体验.doc

    漫画作品与增强现实体验

    漫画作品改编舞台剧经验.doc

    漫画作品改编舞台剧经验

    ,,ABC-DQ:基于MATLAB Simulink的三相静止坐标系到两相静止坐标系(Clark变)到两相旋转坐标系变(Park变)的仿真模型 仿真条件:MATLAB Simulink R2015b

    ,,ABC_DQ:基于MATLAB Simulink的三相静止坐标系到两相静止坐标系(Clark变)到两相旋转坐标系变(Park变)的仿真模型。 仿真条件:MATLAB Simulink R2015b ,MATLAB Simulink;三相静止坐标系;两相静止坐标系;Clark变换;Park变换;仿真模型;R2015b,MATLAB Simulink中的Clark-Park变换仿真模型研究

    武汉东湖高新集团智慧园区 22页PPT(21页).pptx

    在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。

    自驾游中行程时间灵活调整.doc

    自驾游中行程时间灵活调整

    ,,基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样 之后基于抽样序列进行概率潮流计算 最后得到电网的电压概率出力曲线 程序

    ,,基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样 之后基于抽样序列进行概率潮流计算 最后得到电网的电压概率出力曲线 程序有基于matpower和非matpower(效果好一点) ,核心关键词:蒙特卡洛法; 概率潮流; IEEE33节点电网; 光伏风电概率出力模型; 随机抽样; 电压概率出力曲线; matpower; 非matpower方法。,基于蒙特卡洛法的电网概率潮流分析:IEEE33节点光伏风电模型构建与验证

    基于视觉检测的机械臂药品自动分类与搬运仿真系统实现与优化(含详细可运行代码及解释)

    内容概要:本文详细介绍了基于视觉检测的机械臂药品自动分类与搬运仿真的实现方法。首先通过搭建环境和加载相关模型,接着利用 OpenCV 对摄像头捕获的画面进行药瓶识别,再通过 PyBullet 实现机械臂路径规划及其动作控制,最后通过主循环不断地完成对药物的分类抓取操作。为增强系统性能和稳定性进行了多项改进:采用先进的YOLOv8模型实现更精准的物体检测、增加更细致的夹爪开合逻辑提高物品抓取的成功率,同时加入碰撞检测机制保障运动过程的安全性。该仿真是用Python编程语言开发,并涉及多领域的技术集成。 适用人群:适用于自动化设备研究开发的技术专家或从事机器人相关专业学习的研究人员。 使用场景及目标:可用于研究自动化药房、医院仓库管理等医疗物资自动处理流程的设计;帮助理解并实践如何构建一个完整的机器人视觉引导下的机械手作业体系,以及针对具体应用场景提出有效的改进建议和技术路线图。 其他说明:为了使系统更接近真实环境,开发者还可以继续探索更多先进的机器视觉算法,并深入探讨机械臂硬件层面的选择,以期打造出更加智能化的产品应用于各行各业。

    初识Python-公共课-pdf.zip

    初识Python-公共课-pdf.zip

    Anaconda 2023 State of Data Science Report.pdf

    anaconda

    ,,VSC-HVDC仿真模型 Kundur’s 4-machine 2-area power system.pscad柔性直流输电仿真模型,同步机VSGVSM模型,还有多端如张北直流电网以及基本mmc

    ,,VSC-HVDC仿真模型 Kundur’s 4-machine 2-area power system.pscad柔性直流输电仿真模型,同步机VSGVSM模型,还有多端如张北直流电网以及基本mmc逆变器,自己为biye网上收集的一些觉得有用的基础模型,找这个模型就搜了好久,可以传授找模型的一些地方,怕麻烦的可以拿模型,学习基础用还是可以的。 另外可代接电流型HVDCPSCAD的模型设计。 ,VSC-HVDC仿真模型; Kundur's 4-machine 2-area 模型; 柔性直流输电仿真模型; 虚拟同步机VSGVSM模型; 多端直流电网模型; MMC逆变器模型; 模型搜索资源; 模型交易或共享平台; 电流型HVDCPSCAD模型设计。,基于多端柔性直流输电的VSC-HVDC仿真模型研究:含Kundur四机两区电力系统与VSGVSM模型应用

    56页-智慧双碳园区建设方案.pdf

    在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。

Global site tag (gtag.js) - Google Analytics