JUC----Lock框架

【尚硅谷】JUC基础篇(2021版) 大厂必备技术之JUC并发编程 B站直达 2021版: 【尚硅谷】大厂必备技术之JUC并发编程 2022版: 尚硅谷JUC并发编程(对标阿里P6-P7) 课程资料 2021版:尚硅谷高级技术之JUC高并发编程2021最新版 2022版:尚硅谷JUC并发编程与源码分析2022 代码仓库 GitHub: https://github.com/Shiguang-coding/learn-juc Gitee: https://gitee.com/an_shiguang/learn-juc 1、什么是JUC 1.1 阅读详情

JUC指java中并发编程常用的包,即java.util.concurrent。比如常见的原子类,lock框架,线程池,阻塞队列等,都在这个包内。有关于JUC的其他内容我会在后续的文章中阐述,这篇文章的主题是其中的lock框架,也是我们经常用到的并发安全框架。(写的不对的地方请大家多多指教)

为什么出现Lock框架

已经有了synchronized为什么还要有Lock的出现?
1、首先性能方面早已不是问题,1.6之后对synchronized进行了大量优化,所以两者性能相差不多。开发者开始提倡使用synchronized,因为它更安全。
2、出现lock的原因是synchronized存在一些无法解决的问题。比如响应中断
3、lock框架在使用方面更加灵活,比如线程先获得锁A,再获得锁B,然后释放A,获取C,释放B获取D,像这样嵌套式的获取锁,synchronized是无法完成的。
4、Lock可以实现公平锁

Lock提供了一种无条件的、可轮询的、定时的以及可中断的锁获取操作,也是可重入的。

Lock和synchronized的区别

1、synchronized是java的关键字,是jvm层面上的实现。Lock是一个接口,是基于JDK层面的实现,通过这个接口可以实现同步访问。
2、synchronized方式是自动释放锁的,而lock接口的实现必须手动释放锁
3、调试时,因为Lock的非块结构特性,synchronized获取锁的操作可以特定的栈帧关联起来,而Lock不行

Lock接口


public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;  // 可以响应中断
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;  // 可以响应中断
    void unlock();
    Condition newCondition();
}

逐个来说明一下这些方法的用法。

lock()方法

这种方式获取不到锁的话就会进入阻塞状态,和synchronized类似。

		Lock lock = new ReentrantLock();
        lock.lock();
        try {
            //处理事务
        } catch (Exception e) {
            //处理异常
        } finally {
            lock.unlock();//必须手动释放锁
        }
lockInterruptibly()

这种方式获取不到锁仍然会被阻塞,但是它可以接收中断信号,退出阻塞。

public void method() throws InterruptedException {
    lock.lockInterruptibly();
    try {  
     //.....
    }
    finally {
        lock.unlock();
    }  
}

注意:当一个线程获取了锁之后,是不会被interrupt()方法中断的。因为interrupt()方法只能中断阻塞过程中的线程而不能中断正在运行过程中的线程。因此,当通过lockInterruptibly()方法获取某个锁时,如果不能获取到,那么只有进行等待的情况下,才可以响应中断的。与 synchronized 相比,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。

tryLock() & tryLock(long time, TimeUnit unit)

tryLock()不管是否获取到锁都不会阻塞,而是立即返回,成功返回true,失败返回false。tryLock(long time,TimeUnit unit)获取不到锁时会进入阻塞状态,但是指定时间未获取锁,则返回false,否则返回true。

		Lock lock = ...;
        if (lock.tryLock()) {//lock.tryLock(10, TimeUnit.SECONDS)记得处理异常
            try {
                //do something
            } catch (Exception e) {
                //do something for exception
            } finally {
                lock.unlock();
            }
        }
newCondition()

创建一个condition对象,一个Condition和一个lock关联起来。类比于内置锁和内置条件队列。相比内置的条件队列,condition提供了更丰富的功能。有关于条件队列,后面会写一篇专门来讲。

常用的锁

ReentrantLock(独占锁)

ReentrantLock默认是非公平锁,当构造参数为true是公平锁。
在这里说一下公平锁和非公平锁的区别:
在公平锁上,线程将按照他们发出请求的顺序来获取锁,但在非公平的锁上,则允许“插队”:当一个线程请求非公平锁时,如果发出请求的同时锁状态变为可用,那么这个线程将跳过队列中所有等待的线程获取这个锁。

关于ReentrantLock,写一个响应中断的例子吧
如果存在问题,欢迎大家指正!!

public class DoTest2 {
    public void out() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"   out something");
        Thread.sleep(5000);
   }
    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        DoTest2 test = new DoTest2();
        Thread sim = new Thread(() -> {
            lock.lock();
            try {
                test.out();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }

        },"simple");
        Thread sim2 = new Thread(() -> {
            try {
                lock.lockInterruptibly();
                test.out();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        },"simple2");

        sim.start();
        Thread.sleep(1000);//为了让sim先获得锁
        sim2.start();
        sim2.interrupt();
        System.out.println("main  finish");//证明主线程是正常结束的
    }

}

ReadWriteLock(共享锁)

ReadWriteLock是一个接口

public interface ReadWriteLock {
    Lock readLock();//读锁
    Lock writeLock();//写锁,共享
}

读写锁实现的加锁策略中,允许多个读操作同时进行,但每次至允许一个写操作。

ReentrantReadWriteLock

ReentrantReadWriteLock是读写锁的一个实现,在构造时可以选择构造公平或非公平锁。在公平的锁中,等待时间最长的锁将优先获得锁;如果这个锁由读线程占有,另一个线程的请求写入的话,其他读线程都不能获取读锁,直到写线程使用完并释放锁。在非公平锁中,线程获得访问许可的顺序是不确定的。写线程降级为读线程可以,但是读线程不可以升级为写线程(这样会导致死锁)。写入锁只能有唯一的所有者,所以只能由获取锁的线程释放。

举个栗子:

public class DoTest3 {
    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //private Lock r = rwl.readLock();
    //private Lock w = rwl.writeLock();
    private int num = 10;
    public void get() {
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "   num  =  " + num);
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwl.readLock().unlock();
        }
    }
    public void set(int i) {
        rwl.writeLock().lock();
        try{
            num = i;
            System.out.println(Thread.currentThread().getName() + "      num=    " + num);
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rwl.writeLock().unlock();
        }
    }
    public static void main(String[] args) {
        DoTest3 test = new DoTest3();
        for (int i = 1; i <= 10; i++) {
            new Thread(()-> test.get(),"read"+i).start();//测试读的共享
        }
        /*for (int i = 1; i <= 10; i++) {
            int finalI = i;
            new Thread(()-> {
                test.set(finalI); //测试读的互斥
            },"read"+i).start();
        }*/
    }
}
补:为什么不希望所有的锁都是公平的?

从主观来看,公平是一种很好的行为,而不公平则是一种不好的行为,对吗??在执行加锁操作时,公平锁将由于在挂起线程和恢复线程上存在巨大的消耗而极大的降低性能。在实际情况中,统计上的公平性保证——即保证被阻塞的线程最终获得锁,通常已经足够了,实际开销也小的多。有些算法依赖公平的队列以确保它们的正确性,但这些算法并不多见。所以,大多数情况下,公平锁的性能要比非公平锁的性能要低。
在锁竞争激烈下,公平锁低的一个原因就是,在恢复一个被挂起的线程和与该线程真正开始运行之间存在严重的延迟。比如A持有一个锁,B请求这个锁,则B被挂起。当A释放锁,B被唤醒,尝试再次获取锁。而此时有一个C也请求这个锁,那么C可能在B被完全唤醒之前就可以获得、使用以及释放这个锁。这样才是一个双赢的局面,B获取锁的时间并没有延迟,而C更早的获得了锁,吞吐量获得了巨大的提升。
只有当锁的持有时间相对较长,平均获取锁的时间间隔较长,才考虑使用公平锁。

JUC 高并发编程的入门学习 课程内容概览 什么是 JUC Lock 接口 线程间通信 集合的线程安全 多线程锁 Callable 接口 JUC 三大辅助类: CountDownLatch CyclicBarrier Semaphore 读写锁: ReentrantReadWriteLock 阻塞队列 ThreadPool 线程池 Fork/Join 框架 CompletableFuture 1 什么是 JUC 1.1 JUC 简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的。JUC就是 java.u 阅读详情

相关推荐

吃透Java并发七:locks框架

一、juc-locks框架整体分析 早期的JDK版本中,仅仅提供了synchronizd、wait、notify等等比较底层的多线程同步工具,开发人员如果需要开发复杂的多线程应用,通常需要基于JDK提供的这些基础工具进行封装,开发自己的工具类。 JDK1.5之后,Doug Lea设计了JUC并发包,其中java.util.concurrent.locks包下提供了一系列基础的锁工具,用以对sync...

吃透Java 560

【JUC系列】LOCK框架系列一 框架预览

【JUC的LOCK框架系列一】LOCK框架预览

有问题的请私信或关注v【技术印记】留言 553

Python自动化办公:5分钟搞定钉钉群文件自动发送(附完整代码)

本文详细介绍了如何利用Python实现钉钉群文件的自动化发送。通过结合钉钉企业内部应用与群机器人API,构建了包含智能令牌管理、文件上传与消息发送的完整工作流。文章提供了可直接复用的完整代码,并分享了定时任务、目录监听等进阶实战方案,帮助职场人士高效解决重复性文件发送难题,实现办公自动化。

7z8x2c4v6b9的博客 320

Java并发编程系列之三JUC概述

上篇文章为解决多线程中出现的同步问题引入了锁的概念,上篇文章介绍的是Synchronized关键字锁,本篇文章介绍更加轻量级的锁Lock接口及引出JUC的相关知识。 本文不力争阐释清楚JUC框架的所有内容,而是站在一定的高度下,了解Juc下包的设计与实现。 文章目录一、LOCK锁概述二、JUC概述1、Lock框架① 接口: Condition②接口: Lock③接口: ReadWriteLock④抽象类: AbstractOwnableSynchonizer⑤抽象类(long): AbstractQueue

程序员田同学的博客 1037

3A之自动对焦(AF)算法:从Tenegrad到拉普拉斯的清晰度评价实战

本文深入解析自动对焦(AF)算法的核心——清晰度评价函数,通过实战对比Tenegrad、方差、能量梯度、Brenner和拉普拉斯五大经典算法的原理、代码实现与性能。文章详细阐述了各函数在计算速度、抗噪性和单峰性上的优劣,并提供了从仿真测试到硬件部署的优化策略,帮助开发者根据实际场景选择最合适的AF算法。

weixin_29281915的博客 312

深入解析Panfrost驱动:Mali-GPU开源驱动的架构与实现

本文深入解析了Panfrost驱动作为Mali-GPU开源驱动的架构与实现。从诞生背景到硬件架构演进,详细介绍了Panfrost如何突破ARM闭源策略,实现全栈支持。文章还探讨了驱动设计中的关键技术挑战与性能优化策略,为开发者提供了实用的编译部署指南和性能调优方法。

weixin_30790841的博客 551

JUC框架学习--lock锁总结

Locke 接口: 支持予以不同(重入,公平等)的锁规则: 1. 公平锁 2.非公平锁 3.可重入锁 实现lock接口的锁,其构造方法中有 boolean fair参数控制,当fair为 true时,是公平锁,反之为非公平锁。默认是非公平锁。以ReentrantLock为例源码如下: 无参构造: /** * Creates an instance of {@code ReentrantLock}. * This is equivalent .

tangpeng2018的博客 407

【LVGL】学习笔记--(3)界面切换以及显示优化

界面切换和帧率优化

sinat_33408502的博客 1万+

【JUC系列】LOCK框架系列之二 核心基础类 LockSupport

LockSupport

有问题的请私信或关注v【技术印记】留言 232

手把手教你为FPGA项目集成HyperRAM IP核:从AXI接口封装到上板调试全流程

本文详细介绍了如何为FPGA项目集成HyperRAM IP核,涵盖从AXI接口封装到上板调试的全流程。通过对比DDR3L、PSRAM和HyperRAM的性能指标,突出HyperRAM在低功耗和小封装尺寸方面的优势,并提供硬件连接、AXI4-Lite接口设计、状态机优化及调试技巧等实用内容,帮助开发者高效完成FPGA项目中的内存扩展。

weixin_32103009的博客 283

基于 51 单片机的智能手势控制小车设计与实现

智能手势控制小车以STC89C52RC 单片机为控制核心,通过手势识别模块采集用户手势指令,经单片机处理后驱动电机执行前进、后退、左转、右转等动作。该项目融合了传感器技术、单片机编程和电机驱动技术,具有成本低、易实现、互动性强的特点,适合作为嵌入式系统入门实践案例。本项目成功实现了基于 51 单片机的智能手势控制小车,通过 APDS-9960 模块采集手势信号,经单片机处理后驱动电机完成基本动作,验证了 “传感器 + 单片机 + 执行器” 的嵌入式系统设计思路。

weixin_42300449的博客 177

JUC高并发编程

高并发基础

weixin_42072303的博客 2314

ThingsBoard PE专业版解决方案技术文档——温度&湿度

温湿度解决方案

weixin_67440240的博客 817

【JUC系列】LOCK框架系列之六 核心锁类之ReentrantLock

ReentrantLock 什么是可重入锁

有问题的请私信或关注v【技术印记】留言 618

RHCA ---RH442-4

这题考试中是没有的,但我做ex的判分脚本里做了,主要是lab环境swap只有512M的,这样后续改了某几个参数后会造成内存不够用导致异常.这里记得是双>,如果没自信的小伙伴可以在考试开始后第一时间把/etc/fstab先备份一个或者vi进入后手动敲一下。根据题意我们需要分2个768M的分区给swap。用free看swap大小是2.0Gi即可。留意红框中的内容即可,最后w保存退出。这个时候可以重启下机器。

Q先生 640

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

java面试题-JUC基础类介绍

JUC 相关类介绍

qq_33129875的博客 646

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【JUC系列】LOCK框架系列之五 核心锁类AbstractQueuedSynchonizer

初步认识AbstractQueuedSynchonizer

有问题的请私信或关注v【技术印记】留言 619

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【JUC系列】LOCK框架系列之三 同步工具类 CountDownLatch

CountDownLatch

有问题的请私信或关注v【技术印记】留言 426

【JUC系列】LOCK框架系列之七 核心锁类之ReentrantReadWriteLock

ReentrantReadWriteLock----什么是读写锁

有问题的请私信或关注v【技术印记】留言 593

【JUC系列】LOCK框架系列之八 核心锁类之StampedLock

StampedLock 它是java8在java.util.concurrent.locks新增的一个API。 一种基于性能的锁,具有三种用于控制读/写访问的模式。

有问题的请私信或关注v【技术印记】留言 709

JUC并发编程

https://github.com/CL0610/Java-concurrency?tab=readme-ov-file

AlwaysBestSign_X的博客 155

【JUC系列】LOCK框架系列之四 同步工具类Semaphore

【JUC系列】LOCK框架系列之四 Semaphore

有问题的请私信或关注v【技术印记】留言 324

JUC第九讲:类汇总和学习指南

本文是JUC第九讲,对JUC进行知识体系解读,后续的文章还针对几乎所有的核心的类以及常用的`工具类`作了详细的解读; 本文站在一定的高度了解JUC下包的设计和实现;同时对重要的章节提供跳转链接。

Jet_qi的博客 328

JUC(多线程)笔记

JUC1.JUC概述1.1 JUC简介1.2 进程与线程1.3 线程的状态1.3.1 线程状态枚举类1.3.2 wait/sleep的区别1.4 并行与并发1.4.1 串行模式1.4.2 并行模式1.4.3 并发1.4.4 小结(重点)1.5 管程1.6 用户线程和守护线程1.7 创建线程的方式2.Lock接口2.1 Synchronized2.1.1 Synchronized关键字回顾2.1.2 售票案例2.1.3 多线程编程步骤2.2 什么是Lock2.2.1 Lock接口介绍2.2.2 lock2.2

Listen·Rain的博客 724

Java并发JUC总体框架

Java并发JUC总体框架

jsjxb的博客 622

JUC基础

juc基础

qq_44989062的博客 188
上一篇: 深入理解JVM(二)----对象的内存分布和创建
下一篇: 深入理解JVM(三)----Java线程内存模型和线程
mechanic-heaven
博客等级 码龄9年 8粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值