synchronized关键字:多线程资源访问同步性与早期效率低下原因 春节 营销推广计划
发布时间 - 2026-01-18 14:10:40 点击率:次目录

1.1 说一说自己对于 关键字的了解
关键字的作用是解决多个线程访问资源的同步性问题。它能够确保被其修饰的方法或者代码块在任何时刻都只能有一个线程执行。
在 Java 的早期版本里,它属于重量级锁,效率较为低下。这是因为监视器锁()是依靠底层的操作系统的 Mutex Lock 来实现的,并且 Java 的线程是映射在操作系统的原生线程之上的。要挂起或者唤醒一个线程,都得依靠操作系统来帮忙完成。操作系统在实现线程之间的切换时,需要从用户态转换到内核态。这种状态之间的转换需要花费相对较长的时间,且时间成本较高。这就是早期效率低的原因所在。庆幸的是,在 Java 6 之后,Java 官方从 JVM 层面进行了较大优化。所以现在的锁效率优化得很不错了。JDK1.6 对锁的实现引入了诸多优化,像自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术,这些技术能减少锁操作的开销。
1.2 说说自己是怎么使用 关键字,在项目中用到了吗
关键字最主要的三种使用方式:
下面我已一个常见的面试题为例讲解一下 关键字的具体使用。
面试时面试官常常会问:“你了解单例模式吗?请给我手写一下单例模式!给我讲讲用双重检验锁方式实现单例模式的原理吧!”
双重校验锁实现对象单例(线程安全)
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="has"><code class="language-java">public class Singleton { private 类型的变量 uniqueInstance 是 volatile 的且为 static 的,它是 Singleton 类型的单例对象。 private Singleton() { } public static Singleton 获取唯一实例() { 先判断对象是否已经被实例化过,如果没有被实例化过,才进入加锁代码。 如果 uniqueInstance 为 null ,那么 ;如果 uniqueInstance 不为 null ,则 。 //类对象加锁 对 Singleton.class 进行同步操作。 如果 uniqueInstance 为 null ,那么 ;如果 uniqueInstance 不为 null ,则不执行此条件判断 。 Singleton 类创建了一个名为 uniqueInstance 的实例。 } } } 返回唯一实例。 } } </code></pre></p>另外,需要注意 采用 关键字修饰也是很有必要。
使用关键字进行修饰是很有必要的。这段代码实际上是分三步来执行的:第一步,进行某个操作;第二步,执行另一个动作;第三步,完成最后的步骤。
为 分配内存空间初始化 将 指向分配的内存地址
但是 JVM 具备指令重排的特性,所以执行顺序有可能变为 1->3->2。在单线程环境中,指令重排不会出现问题,然而在多线程环境下,会致使一个线程获取到尚未初始化的实例。比如,线程 T1 执行了 1 和 3,这时 T2 调用某个对象后发现该对象不为空,于是就进行返回,但此时该对象还未被初始化。
使用它能够禁止 JVM 的指令重排,从而确保在多线程环境下可以正常运行。
1.3 讲一下 关键字的底层原理
关键字底层原理属于 JVM 层面。
① 同步语句块的情况
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="has"><code class="language-java">类 SynchronizedDemo 是一个公共类。 public void method() { synchronized (this) { System 输出打印“synchronized 代码块”。 } } } </code></pre></p>使用 JDK 自带的 javap 命令来查看类的相关字节码信息。首先要切换到类的对应目录,接着在该目录下执行 javac.java 命令,以生成编译后的.class 文件。之后再执行 javap -c -s -v -l.class 命令。
关键字原理
从上面我们可以看出:
同步语句块的实现运用的是 指令与 指令。其中, 指令所指的是同步代码块的起始位置,而 指令所指明的是同步代码块的结束位置。当执行指令时,线程会尝试获取锁。锁存在于每个 Java 对象的对象头中,通过这种方式来获取锁,这也是 Java 中任意对象可以作为锁的原因。当锁的计数器为 0 时,线程可以成功获取锁,获取后将锁的计数器设为 1,即加 1。相应地,在执行指令后,会将锁的计数器设为 0,表明锁被释放。获取对象锁失败时,当前线程会进行阻塞等待。它会一直等待,直到锁被另一个线程释放。
② 修饰方法的的情况
<p style='margin-bottom:15px;color:#555555;font-size:15px;line-height:200%;text-indent:2em;'> <pre class="has"><code class="language-java">在该类中可以看到对同步机制的运用和相关操作的实现。 public 方法处于同步状态。 System 输出打印 "synchronized 方法"。 } } </code></pre></p>修饰的方法没有特定的指令。取而代之的是标识,此标识表明该方法是同步方法。JVM 通过这个访问标志来辨别一个方法是否被声明为同步方法,进而执行相应的同步调用。
说说 JDK1.6 之后的关键字在底层进行了哪些方面的优化呢?可以详细地介绍一下这些优化的情况吗?
JDK1.6 对锁的实现做了大量优化。其中包括引入偏向锁技术,以减少锁操作的开销。还引入了轻量级锁技术,同样能降低锁操作的开销。同时引入了自旋锁技术,有助于减少锁操作的开销。也引入了适应性自旋锁技术,可减少锁操作的开销。并且引入了锁消除技术,能减少锁操作的开销。还引入了锁粗化技术,可降低锁操作的开销。
锁主要有四种状态,分别是:无锁状态;偏向锁状态;轻量级锁状态;重量级锁状态。它们会随着竞争的加剧而逐步升级。需要注意的是,锁可以升级但不可降级,这种策略的目的是提升获得锁和释放锁的效率。
①偏向锁
引入偏向锁的目的与引入轻量级锁的目的较为相似。二者都是在没有多线程竞争的前提下,旨在减少传统重量级锁使用操作系统互斥量所带来的性能消耗。然而,二者存在差异:轻量级锁在无竞争的情况下,会利用 CAS 操作来替代使用互斥量;而偏向锁在无竞争的情况下,能够将整个同步过程消除掉。
偏向锁的“偏”即偏心之意,意味着会倾向于第一个获取它的线程。若在后续执行中,此锁未被其他线程获取,那么持有偏向锁的线程就无需进行同步。关于偏向锁的原理,可查看《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》第二版的 13 章第三节锁优化。
在锁竞争激烈的场合,偏向锁会失效。因为这种场合下,每次申请锁的线程很可能都不一样。所以在这种场合不应使用偏向锁,否则会得不偿失。需要注意的是,偏向锁失败后,不会立即膨胀为重量级锁,而是先升级为轻量级锁。
② 轻量级锁
如果偏向锁失败,虚拟机不会立刻升级为重量级锁。它会尝试使用一种优化手段,这种手段称为轻量级锁(1.6 之后加入的)。轻量级锁并非是为了替代重量级锁,其本意是在没有多线程竞争的情况下,减少传统重量级锁使用操作系统互斥量所产生的性能消耗,因为使用轻量级锁时,无需申请互斥量。另外,轻量级锁在加锁时用到了 CAS 操作,在解锁时也用到了 CAS 操作。关于轻量级锁加锁和解锁的原理,可以查看《深入理解 Java 虚拟机:JVM 高级特性与最佳实践》第二版的 13 章第三节锁优化。
轻量级锁能提升程序同步性能的依据是绝大部分锁在整个同步周期内不存在竞争,这是经验数据。若没有竞争,轻量级锁利用 CAS 操作避免了互斥操作的开销。然而,若存在锁竞争,除了互斥量开销外,还会额外发生 CAS 操作,所以在有锁竞争的情况下,轻量级锁比传统的重量级锁更慢。如果锁竞争激烈,那么轻量级将很快膨胀为重量级锁!
③ 自旋锁和自适应自旋
轻量级锁失败后,虚拟机为避免线程在操作系统层面真实挂起,还会进行一种被称为自旋锁的优化手段。
互斥同步对性能影响最大的方面是阻塞的实现。因为挂起线程的操作以及恢复线程的操作都需要转入内核态去完成,而用户态转换到内核态是会耗费时间的。
一般线程持有锁的时间不会太长。因为时间不长,仅仅为这点时间去挂起线程或恢复线程是不值得的。所以,虚拟机的开发团队进行了这样的考虑:能否让后面来请求获取锁的线程等待一会儿而不被挂起呢?看看持有锁的线程是否能很快释放锁。要让一个线程等待,只需让线程执行一个忙循环(自旋),而这种技术就被称作自旋。
百度百科对自旋锁的解释:
什么是自旋锁?自旋锁是为了实现对共享资源的保护而提出的一种锁机制。实际上,自旋锁和互斥锁较为相似,它们都是为了解决对某一项资源的互斥使用问题。不管是互斥锁,还是自旋锁,在任何一个时刻,最多只能有一个保持者,也就是说,在任何一个时刻,最多只能有一个执行单元获得锁。然而,两者在调度机制方面略有差异。互斥锁的情况是,如果资源已经被占用,那么资源申请者就只能进入睡眠状态。而自旋锁则不会导致调用者睡眠,倘若自旋锁已经被其他执行单元所保持,调用者就会一直循环,查看该自旋锁的保持者是否已经释放了锁,“自旋”这个词正是因为这样的情况而得名。
自旋锁在 JDK1.6 之前就已被引入,但其默认是关闭的,需通过--XX:+参数来开启。JDK1.6 及之后,就改为默认开启了。需注意,自旋等待不能完全替代阻塞,因其仍需占用处理器时间。若锁被占用时间短,效果就好;若锁被占用时间长,效果则不佳。自旋等待的时间必须有限度。如果自旋达到了限定的次数,然而仍然没有获得锁,那么就应当挂起线程。自旋的次数默认是 10 次,用户能够通过修改--XX:来对其进行更改。
另外,在 JDK1.6 中引入了一种自旋锁。这种自旋锁是自适应的。自适应的自旋锁带来的改进在于:自旋的时间不再是固定的了。它会根据前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定。这样一来,虚拟机变得越来越“聪明”了。
④ 锁消除
锁消除理解起来较为容易。它的意思是,在虚拟机中,即使是编译器在运行时,如果检测到那些共享数据不可能存在竞争的情况,那么就会执行锁消除操作。锁消除能够节省那些没有意义的请求锁所耗费的时间。
⑤ 锁粗化
我们在编写代码时,原则上总是推荐把同步快的作用范围限制得尽量小。只在共享数据的实际作用域进行同步,这样做是为了让需要同步的操作数量尽可能变小。如果存在锁竞争,等待线程就能尽快拿到锁。
大部分情况下,上面的原则没问题。然而,若一系列连续操作都针对同一个对象反复进行加锁和解锁,就会导致很多不必要的性能消耗。
1.5 谈谈 和 的区别
① 两者都是可重入锁
两者均为可重入锁。“可重入锁”的概念为:自身能够再次获取自身的内部锁。例如,有一个线程获取了某对象的锁,而此时该对象锁尚未释放,当它再次想要获取此对象的锁时依然可以获取。倘若不可锁重入,就会引发死锁。同一个线程每次获取锁,锁的计数器都会自增 1,因此必须等到锁的计数器降为 0 时才能释放锁。
② 依赖于 JVM 而 依赖于 API
依赖于 JVM 得以实现。前面我们提到过,虚拟机团队在 JDK1.6 对该关键字进行了诸多优化,然而这些优化是在虚拟机层面完成的,并未直接呈现在我们面前。它是在 JDK 层面实现的,也就是在 API 层面实现的。实现过程需要 lock()方法和特定的语句块(如 try/ 语句块)配合来完成。因此,我们能够通过查看它的源代码,去了解它是怎样实现的。
③ 比 增加了一些高级功能
相比之前,增添了一些较为高级的功能。主要体现在以下三个方面:其一,等待的过程可以被中断;其二,能够实现公平锁;其三,可以实现选择性通知,也就是锁能够绑定多个条件。
如果你想使用上述功能,那么选择是一个不错的选择。
④ 性能已不是选择标准
在 JDK1.6 之前, 的性能与 相比差很多。具体表现为:随着线程数的增加,关键字的吞吐量下降得极为严重,而 则基本保持在一个较为稳定的水平。我认为这从侧面反映出,关键字还有很大的优化空间。后续的技术发展也证实了这一点,我们之前讲过在 JDK1.6 之后,JVM 团队对该关键字做了很多优化。JDK1.6 之后, 和 的性能大致相同。因此,网络上那些以性能为由选择 的文章是错误的!JDK1.6 之后,性能不再是选择 和 的影响因素!并且,虚拟机在未来的性能改进中会更倾向于原生的,所以还是建议在能够满足需求的情况下,优先考虑使用关键字来进行同步!优化后的和一样,在很多地方都是用到了CAS操作。
1.6 说说 关键字和 关键字的区别
关键字和关键字比较
1.7 java.util.
j.u.c 下有大量的应用,这些应用在各个基础类和工具栏中,它们构成了 Java 并发包的基础。后续进行并发编程学习时,可以按照这个路线图来进行学习。
# synchronized关键字:多线程资源访问同步性与早期效率低下原因
# synchronized关键字
# 多线程资源访问同步性与早期效率低下原因
# 的是
# 互斥
# 是在
# 就会
# 操作系统
# 挂起
# 都是
# 情况下
# 加锁
# 引入了
# 多线程
# 进行了
# 是一个
# 它会
# 需要注意
# 给我
# 多个
# 自适应
# 解锁
# 有一个
# 商洛珠宝网站建设
# 官网SEO网站建设
# 北京网站建设详细方案
# 做营销怎样引流推广产品
# 网站怎么做推广方案
# 新北区百度网站优化排名
# 大连建设网站企业
# 邵阳网站建设怎么做
# 金华大型网站建设
# 廊坊网站建设报价单
# 麻城店铺推广招聘网站有哪些
# 顺德区外贸推广营销中心
# 怎么样设计网站推广产品
# 营销培训推广优势
# 西安抖音营销推广收费
# 红包营销推广项目
# 企业微网站营销推广
# 龙江网站建设方案
# 海安市网站推广方案批发
# 广安品牌网站建设
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
微信藏隐私,别人拿手机易看信息?2 种方法教你悄悄给微信上锁
福建百度推广服务费计入什么科目里?,网站推广厂商有哪些平台
从零到一,如何打造个人品牌?,在哪里寻找推广网站信息
刘雨峰SEO介绍,介绍高效搜索引擎优化之路,南平seo公司优选20火星
福建百度推广开户渠道公司有哪些?,网站建设推广术
手机已连网线或WiFi却无法上网?三个原因及解决办法来啦
杭州SEO人才落户攻略,轻松实现职场梦想,享受杭州美好生活,河北seo哪家信誉好
佛山市公司SEO优化平台,助力企业在线营销新篇章,京东网站优化设计
郑州SEO排名探秘,如何找到优质创作源泉?,辽宁seo服务软件排名
SEO未来:如何在变革中抢占先机,迎接数字营销的新纪元,台州网站建设分析和总结
警惕!骗子混入工作群冒充董事长*60万,咋回事?
SEO才能:提升网站排名,突破网络营销的核心竞争力,南宁本地seo营销公司
揭秘SEO优化背后的秘密武器,如何轻松提升网站排名?,大连滨州网站建设推广
SEO站外优化策略:提升网站排名的关键因素,遵义公司网站推广
SEO步骤介绍,亚洲、欧美及中文市场的区别化步骤与方法,上海关键词优化排名厂家
广州百度推广产品分析与选择指南,山西网站建设论文app
福建百度推广的费用高吗?多少钱?,网站建设创意方法
SEO客服:如何提升客户体验与业务转化的双赢策略,鄂州网站建设公司教程
11月19日深圳新版二手房交易网签系统上线,这些重点要注意
探索未知,如何通过SEO优化提升网站流量,市中区关键词seo排名优化
SEO就是:让你的品牌脱颖而出,获得更多曝光与流量,梅岭关键词排名优化
广州百度推广费用高吗?解析影响因素和优化策略,旅游营销策划推广
探索未知,如何利用自媒体营销开启你的品牌新篇章,亳州网站关键词排名优化
滨州SEO优化排名公司,助力企业互联网营销腾飞的秘密武器,seo引擎优化 惠大麦
江夏SEO排名服务,助力企业网站优化,提升在线竞争力,seo实用软件
主体信息查询:国家工商总局及地方工商局网站知多少?
365好商机网:集多种服务于一体,助力创业与招商
SEO分类:从基础到进阶,全面解析SEO优化的关键要素,新建设网站排名
SEO排名不佳?别担心,我这里有一手秘诀!,淮安网站建设哪家好
揭秘成功的自媒体人,如何我用内容打造个人品牌?,荆州关键词排名哪里有
SEO攻略:搜索引擎优化,快速提升网站排名,网站推广网站优化费用
SEO学堂:开启数字营销新时代,全面提升网站排名与流量,文山ai营销推广方案
福建百度推广一天150元能用多久?有效投放策略解析,浙江营销推广选择
SEO入门玄关隔断摆件,打造家居风水与美学的完美融合,亦庄网站整站优化公司
SEO入门玄关鞋柜隔断,打造家居空间新亮点,宁夏seo技巧平台
宁海SEO优化服务,让您的网站在搜索引擎中脱颖而出,装修行业关键词排名前十
个人身份信息被他人绑定微信支付怎么办?查询及解绑方法看这里
SEO立刻:快速提升网站排名,带你走在搜索引擎前沿,网站建设怎么推广好做
扎比微信分身ios版:解决多微信账号登录烦恼,免费又易用
南昌SEO基础知识营销,打造高效网络营销步骤,seo优选12火星软件
SEO查:如何用精准的SEO诊断助力网站流量爆发,美团关键词排名怎么补
日常求人不得?这6款老司机才懂的见光死网站快收藏
以用户体验为核心,打造SEO新境界,seo基础入门知识大全
广州百度推广限流,企业如何应对营销挑战,庐阳区网站建设
SEO留痕:数字营销的隐性力量,如何通过SEO优化让品牌更具竞争力,铁岭网站关键词建设优化
广东SEO优化创新服务,引领企业互联网营销新潮流,seo如何应对网站风险
SEO项目分析,步骤与执行的艺术,兖州市网站优化
广州百度推广黑幕,揭示背后的真相与行业乱象,山东网站建设app
广州个人如何做好百度推广,营销推广的描述怎么写
广州快速SEO优化收费标准介绍,如何选择性价比高的服务,seo网站抉择火星推荐

