Java之多线程里面的锁理解以及synchronized与Lock的区别
一、宏观的说下锁的分类
1)锁分为乐观锁、悲观锁
悲观锁认为对于同一个数据的并发操作,一定是会发生修改的,哪怕没有修改,也会认为修改。因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。
乐观锁则认为对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用尝试更新,不断重新的方式更新数据。乐观的认为,不加锁的并发操作是没有事情的
2)锁分为公平锁、非公平锁
公平锁是指多个线程按照申请锁的顺序来获取锁。
非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。
3)锁分为独享锁、共享锁
独享锁是指该锁一次只能被一个线程所持有。
共享锁是指该锁可被多个线程所持有。
二、java中常见具体高并发锁
1)synchronized
synchronized机制是给共享资源上锁,只有拿到锁的线程才可以访问共享资源,这样就可以强制使得对共享资源的访问都是顺序的,够保证在同一个时刻最多只有一个线程执行同一个对象的同步代码,可保证修饰的代码在执行过程中不会被其他线程干扰
synchronized(obj) {}
synchronized实现的机理依赖于软件层面上的JVM,对于Synchronized而言,也是一种悲观锁、非公平锁、也是独享锁、也是互斥锁。
2)ReentrantLock
可重入锁,顾名思义,这个锁可以被线程多次重复进入进行获取操作
Lock实现的机理依赖于特殊的CPU指令,比如执行lock()方法的时候,cpu发出lock指令,比如我们执行unlock的时候,cpu发出lock指令,可以认为不受JVM的约束,并可以通过其他语言平台来完成底层的实现。在并发量较小的多线程应用程序中,ReentrantLock与synchronized性能相差无几,但在高并发量的条件下,synchronized性能会迅速下降几十倍,而ReentrantLock的性能却能依然维持一个水准,高并发量情况下使用ReentrantLock。
ReentrantLock通过方法lock()与unlock()来进行加锁与解锁操作,与synchronized会被JVM自动解锁机制不同,ReentrantLock加锁后需要手动进行解锁。为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock必须在finally控制块中进行解锁操作。通常使用方式如下所示
Lock lock = new ReentrantLock();try {lock.lock();}finally {lock.unlock();}
对于ReentrantLock而言,ReentrantLock在构造函数中提供了是否公平锁的初始化方式,默认为非公平锁。这是因为,非公平锁实际执行的效率要远远超出公平锁、ReentrantLock也是互斥锁、也是独享锁。
3)Semaphore
互斥是进程同步关系的一种特殊情况,相当于只存在一个临界资源,因此同时最多只能给一个线程提供服务。但是,在实际复杂的多线程应用程序中,可能存在多个临界资源,这时候我们可以借助Semaphore信号量来完成多个临界资源的访问
,通过acquire()与release()方法来获得和释放临界资源,Semaphore和ReentrantLock用法差不多,Semaphore的锁释放操作也由手动进行,因此与ReentrantLock一样,为避免线程因抛出异常而无法正常释放锁的情况发生,释放锁的操作也必须在finally代码块中完成,
构造方法里面也可以设置否公平锁的初始化方式,默认为非公平锁。
4)AtomicInteger
在多线程程序中,诸如++i或i++等运算不具有原子性,是不安全的线程操作之一。通常我们会使用synchronized将该操作变成一个原子操作,但JVM为此类操作特意提供了一些同步类,使得使用更方便,且使程序运行效率变得更高。通常AtomicInteger的性能是ReentantLock的好几倍。
三、各个锁的优势
1.synchronized:
在资源竞争不是很激烈的情况,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,synchronized它是通过悲观锁实现的。
2.ReentrantLock:
在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍,而ReentrantLock确还能维持常态。
高并发量情况下使用ReentrantLock。
3.Atomic:
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步,是基于cas操作来实现的,它是通过乐观锁来实现的。
参考地址:https://youzhixueyuan.com/4-kinds-of-java-thread-locks.html 然后自己再对比比较和精简分析
4 synchronized与Lock的区别
1).首先synchronized是java内置关键字,是在在jvm层面,Lock是一个接口,最后是由CPU来发送lock和unlock指令,这个和volatile底层原理实现类似。
2).synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3 ) .synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4) .用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
5) .synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
6) .Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
Java之多线程里面的锁理解以及synchronized与Lock的区别相关推荐
- 题目:三个售票员 卖出 30张票 || 多线程编程的企业级套路+模板||synchronized与Lock的区别
package com.dym.juc;//资源类 class Ticket {private int number =30;public synchronized void saleTicket() ...
- java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)
java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一) 目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronize ...
- 【java线程】锁机制:synchronized、Lock、Condition
[Java线程]锁机制:synchronized.Lock.Condition 原创 2013年08月14日 17:15:55 标签:Java /多线程 74967 http://www.infoq. ...
- 解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团)
解决多线程安全问题-无非两个方法synchronized和lock 具体原理以及如何 获取锁AQS算法 (百度-美团) 参考文章: (1)解决多线程安全问题-无非两个方法synchronized和lo ...
- Java中synchronized和Lock的区别
前言 最近有一个需求是需要将数据库的一些数据抽取出来放到文件文件命名方式为"FILENAME_yyyyMMddHHmmss",例如FILENAME_20200625120011.计 ...
- Java多线程之Synchronized和Lock的区别
Java多线程之Synchronized和Lock的区别 目录: 原始构成 使用方法 等待是否可以中断 加锁是否公平 锁绑定多个条件Condition 小结:Lock相比较Synchronized的优 ...
- java多线程中 锁 的概念的理解,java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)...
目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...
- 【Java】多线程SynchronizedVolatile、锁升级过程 - 预习+第一天笔记
预习 1.什么是线程 基本概念 我们先从线程的基本概念开始,给大家复习一下,不知道有多少同学是基础不太好,说什么是线程都不知道的,如果这样的话,花时间去补初级内容的课. 什么是叫一个进程? 什么叫一个 ...
- 关于Java的多线程Runnable的个人理解(基础,不讲概念)
背景说明: 在学了Java的多线程(继承Thread,Runnable)以后,我出于好奇,就想知道java到底是不是多线程的,不能它说自己是多线程就是多线程,自己想验证一下,于是我就想测试一下,但继承 ...
最新文章
- leetcode算法题--把数字翻译成字符串
- mysql导出 error1290_解决MySQL导出数据到文件报错:ERROR 1290
- linux 760权限,Linux 文件rwx权限问题 chmod 777 XXX 任何人拥有最高权限
- c语言标准图形库,C语言图形库函数.docx
- Spring 的持久化实例(JDBC, JdbcTemplate、HibernateDaoSupport、JdbcDaoSupport、SqlSessionDaoSupport等)...
- c语言删除双向链表重复元素,求一个双向链表的建立,插入删除的c语言程序完整版的,借鉴一下思想,再多说一下就是能运行的那种...
- javaweb基础知识点记录1
- Go语言学习Day01
- AJAX提交表单数据
- asp.net(C#)网站发布后 Global.asax 里 Application_Error 不执行的问题
- 短信验证码平台应该怎么选择?
- 求职简历-机器学习工程师
- 数据结构练习题——线性表
- 一个网页设计需求方眼中的网页设计
- layui实现报表数据
- 【强烈推荐】Windows 更新疑难解答(转贴)
- 与爱同行,育润走进贫困家庭,助推公益事业
- mapDispatchToProps
- 史上第一张黑洞真身照片终于问世——原来黑洞不是黑的...
- CryEngineV UI 制作