lock锁

2023-11-11

目录

1. lock 基本用法

2. lock公平锁与非公平锁

3. lock注意事项

4. synchronized 与 lock区别


1. lock 基本用法

lock.lock();  
try {
    
} finally {
    lock.unlock()
}


或者
 
try {
    lock.lock();
} finally {
    lock.unlock()
}

public class ThreadLock1 {
    public static void main(String[] args) {
        //1. 创建锁对象
        Lock lock = new ReentrantLock();
        //2. 加锁
        lock.lock();
        try{
            System.out.println("你好");
        }finally {
           // 3. 释放锁
             lock.unlock();   
        }
    }
}

输出:
你好

注意:lock要放到try外,或者try里面的第一行。

原因有两个:
        1. 如果放在 try ⾥⾯,因为 try 代码中的异常导致加锁失败,还会执⾏ finally 释放锁的操作。
        2. unlock 异常会覆盖 try ⾥⾯的业务异常,增加排查错误的难度。

2. lock公平锁与非公平锁

非公平锁:
public class ThreadLock2 {
    private static int number = 0;
    static class Counter {
        //1. 创建锁对象
        private static Lock lock = new ReentrantLock();
        //循环次数
        private static int MAX_COUNT = 1000000;

        public static void incr() {
            for (int i = 0; i < MAX_COUNT; i++) {
                lock.lock();
                try {
                    number++;
                } finally {
                    lock.unlock();
                }
            }
        }

        public static void decr() {
            for (int i = 0; i < MAX_COUNT; i++) {
                lock.lock();
                try {
                    number--;
                } finally {
                    lock.unlock();
                }
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {

        long stime = System.currentTimeMillis();
        Thread t1 = new Thread(() ->{
            Counter.incr();
        });
        t1.start();

        Thread t2 = new Thread(() ->{
            Counter.decr();
        });
        t2.start();

        t1.join();
        t2.join();

        long etime = System.currentTimeMillis();
        System.out.println("最终结果:" + number + "   执行时间:" + (etime - stime));
    }
}

输出:
最终结果:0   执行时间:172
公平锁
修改:
    private static Lock lock = new ReentrantLock(true);

输出:
最终结果:0   执行时间:5382

可以明显看出非公平锁比公平锁性能好很多。 

3. lock注意事项

        1. unlock操作一定要在finally里面。

                会出现的问题:可能会导致锁资源永久占用的问题。

        2. lock()  一定要放在try之前,或者是try的首行。

                会出现问题:a. 未加锁却执行了释放锁的操作。  b. 释放锁的错误信息会覆盖业务报错信息,从而增加调试程序和修复程序的复杂度。

public class ThreadLock4 {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        
        try {
            System.out.println("进入了 try 方法");
            int i = 10 / 0; // 某一种极端的操作
            System.out.println("执行 lock 操作");
            lock.lock();
        } finally {
            System.out.println("执行 unlock 操作");
            lock.unlock();
        }
    }
}



输出:
    进入了 try 方法
    执行 unlock 操作
    Exception in thread "main" java.lang.IllegalMonitorStateException
	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
	at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
	at thread.ThreadLock4.main(ThreadLock4.java:24)
public class ThreadLock4 {
    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        System.out.println("执行 lock 操作");
        lock.lock();
        try {
            System.out.println("进入了 try 方法");
            int i = 10 / 0; // 某一种极端的操作

        } finally {
            System.out.println("执行 unlock 操作");
            lock.unlock();
        }
    }
}

输出:
    执行 lock 操作
    进入了 try 方法
    执行 unlock 操作
    Exception in thread "main" java.lang.ArithmeticException: / by zero
	at thread.ThreadLock4.main(ThreadLock4.java:20)

4. synchronized 与 lock区别

        1. Lock更灵活,有更多的方法。比如,try lock()......

        2. Lock默认是非公平锁,但可以指定为公平锁;synchronized只能为非公平锁。

        3. 调用lock方法和synchronized线程等待锁状态不同,lock方法会变味WAITING,而synchronized会变为BLOCKED。

        4. synchronized是JVM层面提供的锁,它是自定进行加锁和释放锁,对于开发者来说是无感的;而lock需要开发者自己进行加锁和释放锁的操作。

        5. synchronized可以修改方法(静态方法/普通方法) 和代码块;而lock只能修饰代码块。

lock等待时,WAITING状态:

public class ThreadLock5 {
    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        System.out.println("执行lock操作");

        Thread t1 = new Thread(() -> {
            lock.lock();
            System.out.println("线程1得到锁");
            try{
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                System.out.println("线程1释放锁");
                lock.unlock();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {

            try{
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.lock();
            try {
                System.out.println("线程2得到锁");
            }finally {
                System.out.println("线程2释放锁");
                lock.unlock();
            }
        });
        t2.start();

        Thread.sleep(1500);
        System.out.println("线程2: " + t2.getState());
        t1.join();
        t2.join();
    }
}
输出:
执行lock操作
线程1得到锁
线程2: WAITING
线程1释放锁
线程2得到锁
线程2释放锁

public class ThreadLock6 {
    public static void main(String[] args) throws InterruptedException {

        System.out.println("执行synchronized操作");

        Thread t1 = new Thread(() -> {
           synchronized (ThreadLock6.class) {
               System.out.println("线程1得到锁");
           }
            try{
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();

        Thread t2 = new Thread(() -> {

            try{
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (ThreadLock6.class) {
                System.out.println("线程2得到锁");
            }
        });
        t2.start();

        Thread.sleep(1500);
        System.out.println("线程2: " + t2.getState());
        t1.join();
        t2.join();
    }
}

输出:
执行synchronized操作
线程1得到锁
线程2得到锁
线程2: TERMINATED

synchronized 讲解:

synchronized_Youcan.的博客-CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

lock锁 的相关文章

随机推荐

  • 如何统计iOS产品不同渠道的下载量?

    一 前言 在开发过程中 Android可能会打出来很多的包 用于标识不同的商店下载量 原来觉得苹果只有一个商店 AppStore 如何做出不同来源的统计呢 本篇文章就是告诉大家如何做不同渠道来源统计 二 正文 先看一下苹果自家统计到的数据
  • unity局域网开关机步骤一-网络唤醒-设置电脑使允许局域网内其他电脑控制

    被控制端主机的设置 一 Bois界面网络唤醒的设置 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img TR2xwyAx 1593577482582 htts img blog csdnimg cn 20200701
  • 详细及易读懂的 大津法(OTSU)原理 和 比opencv自带更快的算法实现

    OTSU算法原理简述 最大类间方差是由日本学者大津 Nobuyuki Otsu 于1979年提出 是一种自适应的阈值确定方法 算法假设图像像素能够根据阈值 被分成背景 background 和目标 objects 两部分 然后 计算该最佳阈
  • C++之拷贝构造、拷贝赋值

    拷贝构造 class Stu public int no string name int age public Stu int no 10086 string name jin int age 18 no no name name age
  • springboot+mybatis-plus+双数据源

    springboot mybaits plus mybatis plus的双数据源和逆向工程的配置整合 废话不多说直接开始干 mybatis plus逆向工程的配置 public class CodeGenerator Project pa
  • JVM、GC和常用命令

    这是11月份的一个分享 借着组内分享的机会 重新梳理了一遍JVM的一些基本概念和学习资料 在这个PPT中 关于G1的部分比较粗略 最近正在恶补G1的知识 后面可能会单独整理一篇分享出来 需要原件的 可以在我的公众号 duqi Voice 后
  • 【头歌】Linux Linux从入门到精通

    https www educoder net paths 43 第1关 Linux初体验 bin bash 在以下部分写出完成任务的命令 begin cd ls a end 第2关 Linux常用命令 bin bash 在以下部分写出完成任
  • linux ping命令参数说明及使用

    一 参数说明 在控制台输入ping会有参数说明 BusyBox v1 22 1 2019 07 23 15 07 27 CST multi call binary Usage ping OPTIONS HOST Send ICMP ECHO
  • 2018 年,关于深度学习的 10 个预测

    我有一种预感 2018年 所有的事情都会发生巨变 我们在2017年看到的深度学习取得的惊人突破将会以一种强大的方式延续到2018年 2017年在深度学习领域的研究成果将会应用于日常的软件应用中 下面是我对2018年深度学习的10个预测 1
  • 抓取chrome所有版本密码

    文章首发先知社区 https xz aliyun com t 9752 工具已上传到github https github com SD XD Catch Browser 谷歌浏览器存储密码的方式 在使用谷歌浏览器时 如果我们输入某个网站的
  • python 无头模式 绕过检测_python爬虫反反爬虫有绝技,轻松绕开百度人机验证!...

    你可能已经了解到了无头浏览器的作用以及使用的方法 那么本篇文章就让我们一起用无头浏览器做点事情 是的你没有看错 我们要 搞 的对象就是百度指数这个网站 不知道你平时是否会应用到这里面的数据呢 今天的主要目标就是使用无头浏览器登录百度指数网站
  • 离散傅里叶变换MATLAB实现

    文章目录 要求 一 连续函数抽样 二 抽样长度确定 三 DFT 1 使用一次循环实现DFT 2 使用矩阵实现DFT 总结 要求 有一单频信号y t sin 2 ft 其中f 100Hz 和f 500Hz 分别用DFT求y t 的谱 抽样频率
  • 某中学校校园网络方案设计(课程设计)

    目录 一 绪论 1 1 中小学校园信息化应用的现状 1 2 中小学校园网络系统现状 二 需求分析 2 1 获取需求的途径 方法 过程等 2 2基本情况 2 3 建筑分布 2 4 信息点 需联网的设备 分布及数量 表格 三 设计 3 1 设计
  • cesium for ue5中actor的cesium georeference组件的改变(英文教程文档是更新了的)

    今天 重新回顾下cesium for ue的教程 actor添加cesium georeference组件 发现在ue5中 没有这个组件了 忍住卸载ue5 重新安装ue4 27的冲动 cesium的组件数量增多了 反而功能减少了 不可能 绝
  • Unity之UI

    Unity之UGUI 一 Canvas 1 创建Canvas 2 Render Mode 1 Screen Space Overlay 2 Screen Space Camera 3 World Space 3 Pixel Perfect
  • 【计算机毕设项目】基于大数据的社交平台数据爬虫舆情分析可视化系统

    文章目录 0 前言 1 课题背景 2 实现效果 实现功能 可视化统计 web模块界面展示 3 LDA模型 4 情感分析方法 预处理 特征提取 特征选择 分类器选择 实验 5 部分核心代码 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不
  • python智能合约编程_如何用Python Flask开发以太坊智能合约

    将数据存储在数据库中是任何软件应用程序不可或缺的一部分 无论如何控制该数据库都有一个该数据的主控 区块链技术将数据存储到区块链网络内的区块中 因此 只要某个节点与网络同步 它们就会获得区块中数据的副本 因此 该技术中没有特定的数据主控 在本
  • C#学习教程八

    枚举 枚举是C 编程语言的一种类型 跟类 结构 密封类 分布类 委托 事件 抽象都是同一级别的类型 枚举用enum关健字来定义 枚举可以一次性定义一组常量和常量的使用方式一样 枚举通常用在分支语句中 这种做法可以增加程序的可读性 枚举中的每
  • 如何查看和修改linux系统的字符集

    查看系统的字符集 通过locale命令查看系统支持的字符集 这个是很干净的一个系统 root master locale a C en US utf8 POSIX 还有这种对字符集支持比较好的 root master yt locale a
  • lock锁

    目录 1 lock 基本用法 2 lock公平锁与非公平锁 3 lock注意事项 4 synchronized 与 lock区别 1 lock 基本用法 lock lock try finally lock unlock 或者 try lo