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  然后自己再对比比较和精简分析

 

 

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锁适合代码少量的同步问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/287887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实验报告类与对象水井问题_物业设施设备巡检检查对象、周期和频次

点击上方“物业精英俱乐部”,关注公众号,中国物业管理行业精英联盟,中国百强物业企业精英学习平台。来源:百度文库版权归原创作者所有一巡检对象、周期和频次所谓巡检,并不是说将大大小小的所有物业设施都列入巡检范围&#xff0c…

龙芯2K1000LA处理器流片成功,龙芯业务全面转向LoongArch架构

2022年4月底,龙芯2K1000处理器完成了改版芯片(代号龙芯2K1000LA)的功能和性能测试,正在开展用户试用。龙芯2K1000LA在实现与原有版本2K1000引脚和接口兼容的基础上,处理器核更新为基于龙芯自主指令系统架构LoongArch&a…

php基础教程 第十一步 面向对象补充

继承 上一节中学习了php类,以及类方法、类成员变量相关的一些知识,接下来开始学习php类中的继承。本节是上一节的补充。(其实也就是为了保持日更随便发的一篇文) 开始 php继承是继承与父类的所有属性,就像你继承了你…

ArcGIS实验教程——实验十五:拓扑关系创建与编辑

ArcGIS实验视频教程合集:《ArcGIS实验教程从入门到精通》(附配套实验数据) 一、实验描述 1、拓扑关系的概念 拓扑关系是指满足拓扑几何学原理的各空间数据间的相互关系。即用结点、弧段和多边形所表示的实体之间的邻接、关联、包含和连通关系。如:点与点的邻接关系、点与面…

Sql Server 优化 SQL 查询:如何写出高性能SQL语句

1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引…

【Ubuntu】ubuntu物理机安装方法:wubi

在之前的文章里我们曾经详细介绍了如何在虚拟机里安装ubuntu操作系统,但是一些小伙伴希望在自己的电脑里安装一个ubuntu,来感受一下ubuntu的硬体验。下面给大家介绍一种通过wubi的安装方法。 wubi是 Windows Ubuntu-Based Installer 缩写,是一…

Java之ThreadLocal

1 ThreadLocal接口出现原因 使用ThreadLocal保存当前线程的变量值,这样你想获取该变量的值的时候,获取到的都是本线程的变量值,不会获取到其他线程设置的值,早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLo…

server如何调用 thrift_Thrift总结(二)如何快速创建自己的RPC服务

前面介绍了thrift 基础的东西,怎么写thrift 语法规范编写脚本,如何生成相关的语言的接口。不清楚的可以看这个《Thrift总结(一)介绍》。做好之前的准备工作以后,下面就开始如何用Thrift写RPC接口。如何用Thrift写RPC接口1. 打开之前下载的thr…

Hello Playwright:(2)简化部署方式

前言上次的文章Hello Playwright:(1)从开发到部署发表后,有网友留言问,有不有简化部署的方式:下面,提供 2 种可行的方案。方案 1. Copy其实 Playwright 默认是到C:\Users\用户名\AppData\Local\ms-playwright文件夹下查…

ArcGIS实验教程——实验十六:空间数据查询

ArcGIS实验视频教程合集:《ArcGIS实验教程从入门到精通》(附配套实验数据) 一、实验描述 空间数据库查询定义:从空间数据库中找出所有满足属性约束条件和空间约束条件的地理对象。 二、实验内容 (一)属性查询 1、简单查询 2、SQL查询 (二)图形查询 1、点查询 2…

C++入门指南及实战 第一步 概述及经典HelloWorld

本系列文章环境及学习门槛 编程基础:无年龄:具有一定的逻辑思维英文:不要求数学:不要求学习时长:每天一篇,一周4-5篇即可,每篇最多1小时死记硬背:不需要,理解至上本机环…

【数学题】男女的比例

在一个重男轻女的国家里,每家每户都想生男孩。若一户人家生了一个男孩,就不会再生了。若一家生了一个女孩,便会再生一个,直到生下男孩为止。请问这个国家(有无限多的人民)的男女比例是多少?答案:1比1。在某一户人家中…

为什么云服务器没西南的_去年“双11“我买的那台云服务器

一、为什么会买云服务器为什么初学者需要一台云服务器?从我自己那仅有的一点经验来看,重点无非这一个词:实践。细数一下初学者拥有一台云服务器的好处:学习操作系统、熟悉环境大部分初学者在本地使用的是windows系统,在…

Java线程安全以及线程安全的实现方式和内存模型(JMM)

一、了解几个概念 1)临界区: 临界区指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。当有线程进入临界区段时,其他线程或是进…

animate 实现滑动切换效果

今天和大家分享一下用 animate 实现滑动切换效果的小例子 ------- 来自<一只有梦想的前端小白> 大家都知道jQuery 提供的有一下几种方法能够实现滑动效果&#xff1a; slideDown()slideUp()slideToggle()但是以上的滑动不太方便控制其滑动的方向&#xff0c;所以我们还是…

[不一样的依赖注入]通过递归实现容器里依赖注入

递归实现依赖注入创建所需的依赖服务类1public class Test2{3 public void PrintTest()4 {5 Console.WriteLine("Hello World");6 }7}89public class Test2 10{ 11 private readonly Test _test; 12 13 public Test2(Test test) 14 { 15 …

ArcGIS实验教程——实验十七:缓冲区分析(Buffer Analysis)

ArcGIS实验视频教程合集:《ArcGIS实验教程从入门到精通》(附配套实验数据) 【实验描述】 缓冲区(Buffer)是为了识别某一地理实体对周围地物的影响而在其周围建立的一定宽度多边形区域,缓冲区分析(Buffer Analysis)是用来确定不同地理要素的空间临近性或接近程度的一种分…

Java之jdk和CGLib实现动态代理

1 jdk实现动态代理源码实现 这里需要用到InvocationHandler接口 public interface Hello {public void sayHello(); } public class HelloImpl implements Hello {Overridepublic void sayHello() {System.out.println("hello word");} }import java.lang.reflect…

从Visual Studio中生成Linux设备

本文讲的是从Visual Studio中生成Linux设备&#xff0c;【IT168 云计算频道】近日Novell发布了SUSE Studio&#xff1a;一个用于创建Linux设备&#xff08;appliance&#xff09;的工具。与此同时&#xff0c;Mono小组创建了一个插件以从Visual Studio中生成支持SUSE的设备。 …

C++入门指南及实战 第二步 HelloWorld及扩展详解

回顾 在上一节中&#xff0c;我们编写了如下代码&#xff0c;完成了 HelloWorld程序的编写&#xff1a; #include<iostream> using namespace std;int main(){cout <<"Hello World";return 0; }本小节将会对该代码进行讲解&#xff0c;并且解释一下专业…