Java线程锁(一)

Java线程锁(一)在 Linux 系统下 启动一个新的进程必须要给它分配独立的地址空间 建立众多的数据表来维护它的代码段 堆栈段和数据段 这是一种昂贵的多任务工作方式 而在进程中同时运行多个线程 多个线程彼此之间使用相同的地址空间 共享大部分数据 启动一个线程所花费的空间远远小于一个进程所花费的空间 而且线程之间彼此切换所需要的时间远远小于进程之间切换所需要的时间多线程并发面临的挑战 由于多个线程是共同占用所属进程的资源和地址空间的 如果多个线程要同时访问某个资源怎么办 其实在 Java 并发编程中 经常遇到多个线程访问同一个共享

在Linux系统下,启动一个新的进程必须要给它分配独立的地址空间,建立众多的数据表来维护它的代码段,堆栈段和数据段,这是一种昂贵的多任务工作方式。而在进程中同时运行多个线程,多个线程彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于一个进程所花费的空间,而且线程之间彼此切换所需要的时间远远小于进程之间切换所需要的时间

多线程并发面临的挑战:

  1. 多线程资源共享
  2. 线程死锁
  3. 锁的选择

由于多个线程是共同占用所属进程的资源和地址空间的,如果多个线程要同时访问某个资源怎么办?

其实在Java并发编程中,经常遇到多个线程访问同一个 共享资源,这时候作为开发者必须考虑如何维护数据一致性,这就是Java锁机制(同步问题)的来源

Java提供了多种多线程锁机制的实现方式,常见的有:

  • Synchronized
  • ReentrantLock
  • Semaphore
  • Atomiclnteger等

每种机制都有优缺点与各自的适用场景

Synchronized(依赖于JVM,可靠性高,性能随Java版本升级而提高)

在Java中Synchronized关键字被常用于维护数据一致性

Synchronized机制是给共享资源上锁,只有拿到锁的线程才可以访问共享资源,这样就可以强制使得对共享资源的访问都是按顺序的

Synchronized来实现多线程的同步操作是很简单的,在需要同步的对方的代码块,类,方法中加入此关键字,它能保证在同一个时刻最多只有一个线程执行同一个对象的同步代码,可保证修饰的代码在执行过程中不会被其他线程干扰。

当线程使用Synchronized等待锁时 是不能被Thread.interrupt () 中断的,否则会造成线程死锁

Synchronized修饰的代码具有原子性和可见性,在需要进程同步的程序中使用的频率非常高,可满足一般的进程同步要求

ReentrantLock(可重入锁)

ReentrantLock(可重入锁)可以被线程多次重复进行获取操作

ReentrantLock继承接口Lock并实现了接口中定义的方法,除了能完成Synchronized所能完成的所有工作,还提供了可响应中断锁,可轮询锁请求,定时锁等 避免多线程死锁的方法

Lock依赖于特殊的CPU,可以认为不受JVM的约束,可以通过其他语言平台来完成底层的实现

Synchronized与ReentrantLock的性能比

在并发量较小的多线程应用程序中,ReentrantLock与Synchronized性能相差无几

在高并发量的情况下,Synchronized性能迅速下降几十倍,而ReetrantLock的性能仍然维持一个水准

建议:在高并发量的情况下使用ReentrantLock

ReentrantLock引入了两个概念:   公平锁与非公平锁

公平锁指的是锁的分配机制是公平的,通常 先对锁提出获取请求的线程 会先被分配到锁。

非公平锁指的是JVM按随机,就近原则分配锁的机制被称为非公平锁

ReentrantLock在构造函数中提供了是否公平锁的初始化,默认是非公平锁

非公平锁实际执行的效率远超公平锁,除非程序有特殊要求,否则常用非公平锁的分配机制

ReentrantLock通过 lock ()  与 unlock () 来进行加锁与解锁操作,与Synchronized会被JVM自动解锁机制不同,ReentrantLock加锁后需要手动进行解锁

为了避免程序出现异常而无法正常解锁的情况,使用ReentrantLock必须在finally控制块中进行解锁操作 

使用方式的示例代码如下:

Lock lock=new ReentrantLock(); try{ lock.lock(); }catch(){ }finally{ lock.unlock(); }

Semaphore

由于Synchronized和ReentrantLock是互斥锁,互斥是进程同步关系的一种特殊情况,相当于只存在一个临界资源,因此最多只能给一个线程提供服务。在实际复杂的多线程应用程序中可能存在多个临界资源,这时可以借助Semaphore信号量来完成多个临界资源的访问

Semaphore基本能完成ReentrantLock的所有工作,使用方法类似,通过acquire () 与 release () 方法来获取和释放临界资源

Semaphore.accquire () 方法默认为可响应中断锁,与ReentrantLock.lockInterruptibly () 作用效果一致,也就是说在等待临界资源的过程中可以被Thread.interrupt () 方法中断

Semaphore也实现了 可轮询的锁请求 与 定时锁 的功能,除了方法名accquire与lock不同,使用方法与ReentrantLock几乎一致。Semaphore也提供了公平锁与非公平锁机制,也可以在构造函数中进行初始化设定

Semaphore的锁释放操作也由手动进行,与ReentrantLock一样,为避免线程因抛出异常而无法正常释放锁的情况发生,释放锁的操作也必须在finally代码块中完成

AtomicInteger

AtomicInterger是一系列相同类的代表之一,常见的还有AtomicLong等,它们的实现原理都相同,区别就在于运算对象类型的不同

在多线程应用程序中,如++i  ,i++等运算不具有原子性,是不安全的线程操作之一

通常使用Synchronized将该操作变成一个原子操作,但JVM为此类操作特意提供了一些同步类,从而使得更加方便,并且程序运行效率变得更高,

AtomicInteger的性能是ReentrantLock的好几倍

Java线程锁总结:

Synchronized

在资源竞争不是很激烈的情况下,偶尔有同步的情况下,Synchronized是很合适的,因为编译程序通常会尽可能的优化Synchronized,可读性也很好

ReentrantLock

在资源竞争不激烈的情况下,性能稍微比Synchronized差一点,但是当同步很激烈情况下,Synchronized的性能一下子能下降好几十倍,而ReentrantLock依然能维持常态

在高并发量的情况下使用ReentrantLock

Atomic:

在资源竞争不激烈的情况下,性能比Synchronized差一点,而资源竞争激烈的情况下,也能维持常态

在资源竞争激烈的情况下,Atomic的性能会优于ReentrantLock一倍左右

缺点在于,只能同步一个值,一段代码中只能出现一个Atomic的变量,多余一个同步无效,它不能在多个Atomic之间同步

个人建议:

写同步的时候,优先考虑Synchronized,如果有特殊的情况,再进一步优化

ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/214509.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午4:05
下一篇 2026年3月18日 下午4:06


相关推荐

  • deepfakes视频的网站_deepfakes视频的网站[通俗易懂]

    deepfakes视频的网站_deepfakes视频的网站[通俗易懂]{“optioninfo”:{“dynamic”:”true”,”static”:”true”},”simplifiedDisplay”:”newEdition”,”newCard”:[{“link”:”https://www.aliyun.com/product/live”,”icon”:”live”,”title”:”视频直播LIVE”,”des”:”视频直播(ApsaraVideoLive…

    2022年5月26日
    44
  • 原型模式的应用场景_原型模式深浅克隆区别

    原型模式的应用场景_原型模式深浅克隆区别ProtoType 原型模式动机模型定义实例结构要点总结笔记动机在软件系统中,经常面临着”某些结构复杂的对象“的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口如何应对这种变化?如何向”客户程序“(使用这些对象的程序)”隔离出“这些易变对象,从而使得”依赖这些易变对象的客户程序“不随着需求变化而变化?模型定义使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新对象。实例和工厂模型用的同一个实例工厂模式//工厂class SplitterF

    2022年8月11日
    6
  • 10大黑客专用的 Linux 操作系统,每个都很酷!

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 来源:民工哥技术之路    今天列出一些最常用、最受欢迎的Linux发行版来学习黑客和…

    2021年6月26日
    103
  • Java开发手册之索引规约「建议收藏」

    Java开发手册之索引规约「建议收藏」Java开发手册之索引规约

    2022年4月22日
    43
  • 推出AI助手APP“元宝”,能看新闻能搜索

    推出AI助手APP“元宝”,能看新闻能搜索

    2026年3月14日
    1
  • Linux从入门到指令详解

    Linux从入门到指令详解一、概述我们为什么要学习Linuxlinux诞生了这么多年,以前还喊着如何能取代windows系统,现在这个口号已经小多了,任何事物发展都有其局限性都有其天花板。就如同在国内再搞一个社交软件取代腾讯一样,想想而已基本不可能,因为用户已经习惯于使用微信交流,不是说技术上实现不了解而是老百姓已经习惯了,想让他们不用,即使他们自己不用亲戚朋友还是要用,没有办法的事情。用习惯了windows操作系统,再让大家切换到别的操作系统基本上是不可能的事情,改变一个人已经养成的习惯太难。没有办法深入到普通老百姓的生

    2022年6月5日
    31

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号