多把锁+ReentrantLock+活锁+死锁

目录

多把锁

 活跃性

 定位死锁

例题:哲学家问题 

活锁

 饥饿

ReentrentLock锁

用法

打断锁 

tryLock()设置超时方法

 哲学家问题优化——ReentrantLock解决死锁

公平锁


 

多把锁

并发度:

同一个时间节点上,可能与服务端进行交互的用户个数;

如何增强并发度:

首先明确,并发度增强无非就是交互个数在一个时间点上变多——>那么我们可以设置多把锁。目的就是同一时间上交互变多;

例子:

package com.example.juc.Multi;import lombok.extern.slf4j.Slf4j;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.TestMultiLock")
public class TestMultiLock {public static void main(String[] args) {BigRoom room = new BigRoom();/***room中的sleep与study方法锁资源是不一致的* 有利于增强并发度,不过容易发生死锁*///1.小明线程睡觉new Thread(()->{try {room.sleep();} catch (InterruptedException e) {e.printStackTrace();}},"小明").start();//2.小花线程学习new Thread(()->{try {room.study();} catch (InterruptedException e) {e.printStackTrace();}},"小花").start();}
}
@Slf4j(topic = "c.BigRoom")
class BigRoom{//1.提供两种房间,一个睡觉的一个学习的,两个业务分开private final Object studyRoom=new Object();private final Object bedRoom=new Object();public void sleep() throws InterruptedException {synchronized (bedRoom){log.debug("睡2秒");Thread.sleep(2000);}}public void study() throws InterruptedException {synchronized (studyRoom){log.debug("学习1s");Thread.sleep(1000);}}
}


 活跃性

死锁:相互调用对方的同步资源,但是锁资源又都没释放

例子:

package com.example.juc.Multi;import lombok.extern.slf4j.Slf4j;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.DeadLock")
public class DeadLock {public static void main(String[] args) {testDead();}public static void testDead(){//1.锁资源Object A=new Object();Object B=new Object();Thread t1=new Thread(()->{synchronized (A){log.debug("即将lock B");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (B){log.debug("lock B完成");}}},"t1");t1.start();Thread t2=new Thread(()->{synchronized (B){log.debug("即将lock A");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (A){log.debug("log A完成");}}});t2.start();}
}

 定位死锁

jps:列出执行进程

jstack 进程号找到信息

 或者用jconsle(可视化)


例题:哲学家问题 

一方等待另一方释放资源——>而另一方也在等待其他线程释放资源;

package com.example.juc.Multi;import lombok.extern.slf4j.Slf4j;/*** @author diao 2022/4/10*/@Slf4j(topic = "c.TestDeadLock2")
public class TestDeadLock2 {public static void main(String[] args) {//0.创建5个筷子对象Chopstick chopstick1 = new Chopstick("1");Chopstick chopstick2 = new Chopstick("2");Chopstick chopstick3 = new Chopstick("3");Chopstick chopstick4 = new Chopstick("4");Chopstick chopstick5 = new Chopstick("5");new People("小明",chopstick1,chopstick2).start();new People("小花",chopstick2,chopstick3).start();new People("小强",chopstick3,chopstick4).start();new People("小黑",chopstick4,chopstick5).start();new People("小安",chopstick5,chopstick1).start();}}
@Slf4j(topic = "c.People")
class People extends Thread{//1.两个锁资源:左边筷子和右边筷子Chopstick left;Chopstick right;final String name;public People(String name,Chopstick left, Chopstick right) {this.left = left;this.right = right;this.name=name;}//2.重写Thread的run方法@Overridepublic void run() {while(true){//2.1一直循环,集齐左右筷子即可触发eatlog.debug("{}拿筷子",name);synchronized (left){log.debug("{}拿左筷子",name);synchronized (right){log.debug("{}拿右筷子",name);try {eat();} catch (InterruptedException e) {e.printStackTrace();}}}}}private static void eat() throws InterruptedException {log.debug("eating...");//当前线程吃了后,其他线程竞争拿筷子sleep(1000);}
}class Chopstick{String name;public Chopstick(String name) {this.name = name;}
}

当每个人都拿一根筷子的时候就放下,deadLock


活锁

简单来说,就是一个造,一个解决——>导致一直解决不了,比如说20个数,一个线程减,一个线程加,就跟永动机一样;

package com.example.juc.Multi;import lombok.extern.slf4j.Slf4j;import static java.lang.Thread.sleep;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.LiveLockTest")
public class LiveLockTest {//1.锁资源static volatile int count=10;static final Object lock=new Object();public static void main(String[] args) {//2.加减线程new Thread(()->{//2.1当减到count<=0结束while(count>0){try {sleep(20);} catch (InterruptedException e) {e.printStackTrace();}count--;log.debug("当前count{}",count);}},"t1").start();new Thread(()->{while(count<20){try {sleep(20);} catch (InterruptedException e) {e.printStackTrace();}count++;log.debug("当前count{}",count);}},"t2").start();}
}

 饥饿

 我们可以按照顺序加锁,而不是一个线程先获取A,另一个获取B,然后第一个线程再获取B;

我们这个顺序加锁就可以直接先获取AB,就不会出现死锁了;


ReentrentLock锁

可中断:持有锁的线程一直不释放资源的情况下,处于阻塞状态的等待线程可以放弃等待;

支持多个条件变量:意思就是支持多个waitSet(多个条件)——>多个休息室

回顾一下:进入休息室的条件就是拥有锁资源,但是又放弃了,所以得在获取锁资源的条件下——>ReentrentLock特别在于不同条件会放在不同的waitSet中——>有利于减少唤醒次数;

共同点:支持可重入;

用法

 

package com.example.juc.ReengtrantLock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.ReentrantLock;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.ReentrantLock")
public class ReentrantLockTest {//1.锁资源private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {//2.上锁lock.lock();try {log.debug("进入主方法");m1();} finally {lock.unlock();}}public static void m1() {lock.lock();try {log.debug("进入m1方法");m2();} finally {lock.unlock();}}public static void m2(){lock.lock();try {log.debug("进入m2方法");} finally {lock.unlock();}}
}

打断锁 

lock.lockInterruptibly():当获取不到锁资源,就暂停往下执行

t1.interrupt():打断t1线程,结束等待的意思,如果t1线程获取不到锁资源,就会直接退出等待,抛出异常;——>停止无限期的等待,比如死锁

这两个方法时配合起来用的;

 

 


tryLock()设置超时方法

package com.example.juc.ReengtrantLock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.Test21")
public class Test21 {private static ReentrantLock lock = new ReentrantLock();public static void main(String[] args) {Thread t1 = new Thread(() -> {log.debug("尝试获得锁");try {//会等待指定时间,如果在指定时间得到锁资源,则向下执行if(!lock.tryLock(5, TimeUnit.SECONDS)){log.debug("获取不到锁");return;}} catch (InterruptedException e) {//因为lock.tryLock()也是可以被打断的e.printStackTrace();log.debug("获取不到锁");return;}try {log.debug("获得到锁");} finally {lock.unlock();}}, "t1");//主线程先获取锁lock.lock();log.debug("主线程获取到锁");t1.start();}
}

可以发现:

锁对象.tryLock()——>可以设置锁的等待时间,如果在指定时间内都没有得到锁资源就会不往下执行了;

 作用:避免无休止的等待,类似于保护性暂停模式;


 哲学家问题优化——ReentrantLock解决死锁

思路:当一个人只有一根筷子,而另一跟筷子在别人手里时,我们会释放掉当前手中的筷子谦让给别人——>目的:减少饥饿,让每个人都吃得上饭

package com.example.juc.ReengtrantLock;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.locks.ReentrantLock;/*** @author diao 2022/4/10*/
@Slf4j(topic = "c.TestDeadLock3")
public class ReentrantLockTest3 {public static void main(String[] args) {//0.创建5个筷子对象Chopstick chopstick1 = new Chopstick("1");Chopstick chopstick2 = new Chopstick("2");Chopstick chopstick3 = new Chopstick("3");Chopstick chopstick4 = new Chopstick("4");Chopstick chopstick5 = new Chopstick("5");new People("小明",chopstick1,chopstick2).start();new People("小花",chopstick2,chopstick3).start();new People("小强",chopstick3,chopstick4).start();new People("小黑",chopstick4,chopstick5).start();
//         new People("小安",chopstick5,chopstick1).start();//将锁对象换位置,但是会导致某些线程饥饿,一直获取不到锁资源new People("小安",chopstick1,chopstick5).start();}
}/*** 线程People*/
@Slf4j(topic = "c.People")
class People extends Thread{final String name;Chopstick left;Chopstick right;public People(String name, Chopstick left, Chopstick right) {this.name = name;this.left = left;this.right = right;}@Overridepublic void run() {while(true){//1.尝试获得左筷子if(left.tryLock()){try {//2.尝试获得右手筷子if(right.tryLock()){try {eat();} catch (InterruptedException e) {e.printStackTrace();}finally {//3.有得话eat完就给放了right.unlock();}}}finally {//4.第二个if判断失败,释放左手筷子left.unlock();}}}}public static void eat() throws InterruptedException {log.debug("eating...");//线程eat后需要思考1ssleep(1000);}
}/*** 把筷子当做锁对象,而不用synchronized* 继承ReentrantLock即可*/
class Chopstick extends ReentrantLock {String name;public Chopstick(String name) {this.name = name;}
}


公平锁

什么叫不公平: 当你多个线程再等待队列里面进行等待时,获取锁资源,多个竞争一个,而不是按照进入队列时间来竞争,所以是不公平的;

ReentrantLock:可以通过构造方法设置公平还是不公平

公平锁:先进先得;——>解决饥饿问题;——>缺点:会降低并发度

但是我们可以用tryLock()方法来解决;

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

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

相关文章

重磅出击,20张图带你彻底了解ReentrantLock加锁解锁的原理

最近是上班忙项目&#xff0c;下班带娃&#xff0c;忙的不可开交&#xff0c;连摸鱼的时间都没有了。今天趁假期用图解的方式从源码角度给大家说一下ReentrantLock加锁解锁的全过程。系好安全带&#xff0c;发车了。 简单使用 在聊它的源码之前&#xff0c;我们先来做个简单的…

深入源码谈谈ReentrantLock中的公平锁和非公平锁的加锁机制

前言 ReentrantLock和synchronized一样都是实现线程同步&#xff0c;但是像比synchronized它更加灵活、强大、增加了轮询、超时、中断等高级功能&#xff0c;可以更加精细化的控制线程同步&#xff0c;它是基于AQS实现的锁&#xff0c;他支持公平锁和非公平锁&#xff0c;同时…

【图解】一篇搞定ReentrantLock的加锁和解锁过程

文章目录 1. 概述2. AbstractQueuedSynchronizer&#xff08;AQS&#xff09;3. 加锁4. 解锁5. 公平锁和非公平锁的区别 1. 概述 本文主要结合图片分析ReentrantLock加锁和解锁过程的源码&#xff0c;加锁和解锁的原理不清楚的读者可以好好看看。 2. AbstractQueuedSynchroni…

Lock锁和ReentrantLock锁

前言 JDK 1.5中提供的锁的接口java.util.concurrent.locks.Lock&#xff0c;其提供了一些ReentrantLock, ReentrantReadWriteLock实现类。 参考JDK文档&#xff1a;Java Platform SE 6 目录 前言 Lock接口 ReentrantLock 公平性和非公平性 公平锁与非公平锁的使用示例 A…

ReentrantLock源码分析(一)加锁流程分析

一、ReetrantLock的使用示例 static ReentrantLock lock new ReentrantLock(); public static void main(String[] args) throws InterruptedException { new Thread(ClassLayOutTest::reentrantLockDemo, "threadA").start(); Thread.sleep(1000);…

Lock与ReentrantLock

Lock Lock位于java.util.concurrent.locks包下&#xff0c;是一种线程同步机制&#xff0c;就像synchronized块一样。但是&#xff0c;Lock比synchronized块更灵活、更复杂。 1. Lock继承关系 2. 官方文档解读 3. Lock接口方法解析 public interface Lock {// 获取锁。如果锁…

ReentrantLock介绍

文章目录 ReentrantLock1、构造函数2、公平性锁和非公平性锁&#xff08;1&#xff09;公平性锁和非公平性锁示例&#xff08;2&#xff09;公平锁和非公平锁的实现公平性锁&#xff1a;FairLock非公平性锁 &#xff08;3&#xff09;Condition生产者和消费者 循环打印ABC Reen…

ReentrantLock锁相关方法

目录 Lock接口的实现类 ReentrantLock的方法 ReentrantLockTest测试 用于测试的线程 t1测试 正确释放重入锁 获取当前的重入次数 t1t2测试 使用islocked()方法检测锁状态 t1t3测试 使用trylock方法尝试获取锁 使用isHeldByCurrentThread方法检测当前线程是否持有锁 不…

ReentrantLock详解

目录 一、ReentrantLock的含义 二、RerntrantLock当中的常用方法 ①lock()和unlock()方法 ②构造方法 ③tryLock()方法 tryLock()无参数 tryLock(timeout,Times)有参数 ④lockInterruptibly() throws InterruotedException 经典面试问题: ReentrantLock和synchronized有什…

OpenAI最新官方ChatGPT聊天插件接口《智能聊天插件引言》全网最详细中英文实用指南和教程,助你零基础快速轻松掌握全新技术(一)(附源码)

Chat Plugins Limited Alpha 聊天插件 前言IntroductionPlugin flow 插件流其它资料下载 Learn how to build a plugin that allows ChatGPT to intelligently call your API. 了解如何构建允许ChatGPT智能调用API的插件。 前言 在现代的软件开发环境中&#xff0c;使用第三方…

Pycharm快速入门(10) — 插件管理

1、插件安装 File | Settings | Plugins | Marketplace 搜索插件点击Install安装 2、插件卸载 File | Settings | Plugins | Installed 选择需要卸载的插件&#xff0c;点击Uninstall。 3、推荐插件 &#xff08;1&#xff09;、Chinese ​(Simplified)​ Language Pack &am…

chatgpt赋能python:Python编程的好玩之处:用简单的代码创造奇妙的世界

Python编程的好玩之处&#xff1a;用简单的代码创造奇妙的世界 如果你喜欢写代码&#xff0c;那么Python是一个不错的选择。Python语言设计简单&#xff0c;易学易用&#xff0c;同时还拥有丰富的生态系统&#xff0c;支持许多强大的第三方库和框架&#xff0c;可以使你轻松地…

chatgpt赋能python:Python图片拼图的好处和应用

Python图片拼图的好处和应用 Python是一种高级编程语言&#xff0c;已经被广泛应用于数据科学、网络编程、机器学习等领域。其中&#xff0c;Python的图像处理领域也越来越受关注。在本文中&#xff0c;我们将介绍如何使用Python创建图片拼图&#xff0c;并讨论它的好处和应用…

midjourney教程:如何快速生成个性化Logo设计

midjourney是一款基于人工智能技术的Logo设计工具&#xff0c;它可以帮助用户快速生成个性化的Logo设计&#xff0c;而无需具备专业的设计技能。下面将为大家介绍midjourney的使用方法&#xff0c;以帮助大家轻松生成符合自己需求的Logo设计。 第一步&#xff1a;登录midjourn…

chatgpt赋能python:Python添加图片背景的方法

Python添加图片背景的方法 简介 Python是一种开源的高级编程语言&#xff0c;广泛应用于各个行业中&#xff0c;包括图像处理。添加图片背景是图像处理中的常见需求&#xff0c;通过Python可以很方便地实现。 本篇文章将介绍如何使用Python来给图片添加背景&#xff0c;让您…

chatgpt赋能python:Python怎么做图形

Python怎么做图形 在数据可视化和图像处理方面&#xff0c;Python已经成为了最受欢迎的编程语言之一。Python的图形库使得创建各种图形和图表、可视化工具和图像处理应用程序变得容易而简单。 在本文中&#xff0c;我们将会介绍一些最受欢迎的Python图形库&#xff0c;以帮助…

程序员晒追女神聊天截图,坦言第一次没经验,网友直呼凭实力单身

前段时间网络上一名程序员晒出了自己与女神之间的聊天记录的对话截图&#xff0c;通过截图中我们可以看出&#xff0c;应该是这位程序员在追求这位女神&#xff0c;但是短短的十几分钟几条聊天记录&#xff0c;却以女神不再愿意搭理程序员结束&#xff0c;对于这样的结局&#…

程序员给女友4千生活费,收到女友错发信息后分手,神对话!

如何平衡好亲情爱情的关系&#xff0c;是一门学问&#xff0c;有的人就希望自己的另一半过好他们自己的小日子&#xff0c;不要对家里的事情过多的付出&#xff0c;但有人觉得自己父母养大自己不容易&#xff0c;能有能力的话&#xff0c;不光孝敬爹妈&#xff0c;还会帮衬家里…

程序员就是这样聊天把女朋友聊没的

身为程序员 都想当然的认为 身为一个优秀的程序员 我怎么可能会没女票 这不科学啊 工资高&#xff0c;话少 有一天看到了 某个程序员的聊天记录 有女孩主动搭讪 这么绝好的机会 然后你竟然说忙 说忙 忙... 主动找你搭讪 你还不抓紧机会约约约 如果改成&#xff1a…

被程序员的相亲规划整不会了......

近日&#xff0c;北京一程序员将自己7天7场相亲行程规划表发到论坛分享&#xff0c;感叹到&#xff1a;真不是凡尔赛&#xff0c;相亲比上班还难&#xff0c;引来大量网友围观。 相亲也有规划表&#xff1f; 据介绍&#xff0c;该程序员今年刚好30岁&#xff0c;自己平时加班多…