当前位置: 首页 > news >正文

全球跨境电商平台快速优化排名公司推荐

全球跨境电商平台,快速优化排名公司推荐,如何做电商网站设计,怎么做盗号网站多把锁 一间大屋子有两个功能:睡觉、学习,互不相干。 现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低 解决方法是准备多个房间(多个对象锁&#xf…

多把锁

一间大屋子有两个功能:睡觉、学习,互不相干。
现在小南要学习,小女要睡觉,但如果只用一间屋子(一个对象锁)的话,那么并发度很低
解决方法是准备多个房间(多个对象锁)
例子

class BigRoom {private final Object studyRoom = new Object();private final Object bedRoom = new Object();public void sleep() {synchronized (bedRoom) {log.debug("sleeping 2 小时");Sleeper.sleep(2);}}public void study() {synchronized (studyRoom) {log.debug("study 1 小时");Sleeper.sleep(1);}}}

将锁的粒度细分

  • 好处,是可以增强并发度
  • 坏处,如果一个线程需要同时获得多把锁,就容易发生死锁

活跃性

死锁

有这样的情况:一个线程需要同时获取多把锁,这时就容易发生死锁
t1 线程 获得 A对象 锁,接下来想获取 B对象 的锁 t2 线程 获得 B对象 锁,
接下来想获取 A对象 的锁 例:

Object A = new Object();Object B = new Object();Thread t1 = new Thread(() -> {synchronized (A) {log.debug("lock A");sleep(1);synchronized (B) {log.debug("lock B");log.debug("操作...");}}}, "t1");Thread t2 = new Thread(() -> {synchronized (B) {log.debug("lock B");sleep(0.5);synchronized (A) {log.debug("lock A");
log.debug("操作...");}}}, "t2");t1.start();t2.start();

结果

12:22:06.962 [t2] c.TestDeadLock - lock B 
12:22:06.962 [t1] c.TestDeadLock - lock A 

定位死锁

  • 检测死锁可以使用 jconsole工具,或者使用 jps 定位进程 id,再用 jstack 定位死锁:
cmd > jpsPicked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-812320 Jps22816 KotlinCompileDaemon33200 TestDeadLock              // JVM 进程
11508 Main28468 Launcher

cmd > jstack 33200Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-82018-12-29 05:51:40Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.91-b14 mixed mode):"DestroyJavaVM" #13 prio=5 os_prio=0 tid=0x0000000003525000 nid=0x2f60 waiting on condition 
[0x0000000000000000]java.lang.Thread.State: RUNNABLE"Thread-1" #12 prio=5 os_prio=0 tid=0x000000001eb69000 nid=0xd40 waiting for monitor entry 
[0x000000001f54f000]java.lang.Thread.State: BLOCKED (on object monitor)at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)- waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)- locked <0x000000076b5bf1d0> (a java.lang.Object)at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)"Thread-0" #11 prio=5 os_prio=0 tid=0x000000001eb68800 nid=0x1b28 waiting for monitor entry 
[0x000000001f44f000]java.lang.Thread.State: BLOCKED (on object monitor)at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)- waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)- locked <0x000000076b5bf1c0> (a java.lang.Object)at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)// 略去部分输出
Found one Java-level deadlock:============================="Thread-1":waiting to lock monitor 0x000000000361d378 (object 0x000000076b5bf1c0, a java.lang.Object),which is held by "Thread-0""Thread-0":waiting to lock monitor 0x000000000361e768 (object 0x000000076b5bf1d0, a java.lang.Object),which is held by "Thread-1"Java stack information for the threads listed above:==================================================="Thread-1":at thread.TestDeadLock.lambda$main$1(TestDeadLock.java:28)- waiting to lock <0x000000076b5bf1c0> (a java.lang.Object)- locked <0x000000076b5bf1d0> (a java.lang.Object)at thread.TestDeadLock$$Lambda$2/883049899.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)"Thread-0":at thread.TestDeadLock.lambda$main$0(TestDeadLock.java:15)- waiting to lock <0x000000076b5bf1d0> (a java.lang.Object)- locked <0x000000076b5bf1c0> (a java.lang.Object)at thread.TestDeadLock$$Lambda$1/495053715.run(Unknown Source)at java.lang.Thread.run(Thread.java:745)Found 1 deadlock.      
  • 避免死锁要注意加锁顺序
  • 另外如果由于某个线程进入了死循环,导致其它线程一直等待,对于这种情况 linux 下可以通过 top 先定位到 CPU 占用高的 Java 进程,再利用 top -Hp 进程id 来定位是哪个线程,最后再用 jstack 排查

活锁

活锁出现在两个线程互相改变对方的结束条件,最后谁也无法结束,例如

public class TestLiveLock {static volatile int count = 10;
static final Object lock = new Object();public static void main(String[] args) {new Thread(() -> {// 期望减到 0 退出循环
while (count > 0) {sleep(0.2);count--;log.debug("count: {}", count);}}, 
"t1").start();new Thread(() -> {// 期望超过 20 退出循环
while (count < 20) {sleep(0.2);count++;log.debug("count: {}", count);}},"t2").start()}, 
}

饥饿

饥饿定义为,一个线程由于优先级太低,始终得不到 CPU 调度执行,也不能够结束,饥饿的情况不
易演示,讲读写锁时会涉及饥饿问题
下面我讲一下我遇到的一个线程饥饿的例子,先来看看使用顺序加锁的方式解决之前的死锁问题
在这里插入图片描述

顺序加锁的解决方案
在这里插入图片描述

ReentrantLock

相对于 synchronized 它具备如下特点

  • 可中断
  • 可以设置超时时间
  • 可以设置为公平锁
  • 支持多个条件变量

与 synchronized 一样,都支持可重入
基本语法

// 获取锁
reentrantLock.lock();try {// 临界区
} finally {// 释放锁
reentrantLock.unlock();}

可重入
可重入是指同一个线程如果首次获得了这把锁,那么因为它是这把锁的拥有者,因此有权利再次获取这把锁如果是不可重入锁,那么第二次获得锁时,自己也会被锁挡

可打断
一个线程在等待锁的过程中,可以被其他线程打断而提前结束等待

ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(() -> {log.debug("启动...");try {lock.lockInterruptibly();} 
catch (InterruptedException e) {e.printStackTrace();log.debug("等锁的过程中被打断");return;}try {log.debug("获得了锁");} 
finally {lock.unlock();}}, "t1");lock.lock();log.debug("获得了锁");t1.start();try {sleep(1);t1.interrupt();log.debug("执行打断");} finally {lock.unlock();}

输出

18:02:40.520 [main] c.TestInterrupt - 获得了锁 
18:02:40.524 [t1] c.TestInterrupt - 启动... 
18:02:41.530 [main] c.TestInterrupt - 执行打断 
java.lang.InterruptedException 
at 
java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898) 
at 
java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222) 
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335) 
at cn.onenewcode.n4.reentrant.TestInterrupt.lambda$main$0(TestInterrupt.java:17) 
at java.lang.Thread.run(Thread.java:748) 
18:02:41.532 [t1] c.TestInterrupt - 等锁的过程中被打断

锁超时
如果某个线程在规定的时间内无法获取到锁,就会超时放弃.可以一定限度防止死锁。

ReentrantLock lock = new ReentrantLock();Thread t1 = new Thread(() -> {log.debug("启动...");try {if (!lock.tryLock(1, TimeUnit.SECONDS)) {log.debug("获取等待 1s 后失败,返回");return;}} 
catch (InterruptedException e) {e.printStackTrace();}try {log.debug("获得了锁");} 
finally {lock.unlock();}}, "t1");lock.lock();log.debug("获得了锁");t1.start();try {sleep(2);} finally {lock.unlock();}

输出

18:19:40.537 [main] c.TestTimeout - 获得了锁 
18:19:40.544 [t1] c.TestTimeout - 启动... 
18:19:41.547 [t1] c.TestTimeout - 获取等待 1s 后失败,返回 

不公平锁
表示获取锁的抢占机制,是随机获取锁的,和公平锁不一样的就是先来的不一定能拿到锁, 有可能一直拿不到锁,所以结果不公平。

ReentrantLock 默认是不公平的

ReentrantLock lock = new ReentrantLock(false);lock.lock();for (int i = 0; i < 500; i++) {new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + " running...");} 
finally {lock.unlock();}}, "t" + i).start();
} // 1s 之后去争抢锁
Thread.sleep(1000);new Thread(() -> {System.out.println(Thread.currentThread().getName() + " start...");lock.lock();try {System.out.println(Thread.currentThread().getName() + " running...");} finally {lock.unlock();}}, "强行插入").start();lock.unlock();

强行插入,有机会在中间输出

t39 running... 
t40 running... 
t41 running... 
t42 running... 
t43 running... 
强行插入 start... 
强行插入 running... 
t44 running... 
t45 running... 
t46 running... 
t47 running... 
t49 running... 

条件变量
synchronized 中也有条件变量,就是我们讲原理时那个 waitSet 休息室,当条件不满足时进入 waitSet 等待
ReentrantLock 的条件变量比 synchronized 强大之处在于,它是支持多个条件变量的,这就好比

  • synchronized 是那些不满足条件的线程都在一间休息室等消息
  • 而 ReentrantLock 支持多间休息室,有专门等烟的休息室、专门等早餐的休息室、唤醒时也是按休息室来唤醒

使用要点:

  • await 前需要获得锁
  • await 执行后,会释放锁,进入 conditionObject 等待
  • await 的线程被唤醒(或打断、或超时)取重新竞争 lock 锁
  • 竞争 lock 锁成功后,从 await 后继续执行
static ReentrantLock lock = new ReentrantLock();static Condition waitCigaretteQueue = lock.newCondition();static Condition waitbreakfastQueue = lock.newCondition();static volatile boolean hasCigrette = false;static volatile boolean hasBreakfast = false;public static void main(String[] args) {new Thread(() -> {try {lock.lock();while (!hasCigrette) {try {waitCigaretteQueue.await();} 
catch (InterruptedException e) {e.printStackTrace();}}log.debug("等到了它的烟");} 
finally {lock.unlock();}}).start();new Thread(() -> {try {lock.lock();while (!hasBreakfast) {try {waitbreakfastQueue.await();} 
catch (InterruptedException e) {e.printStackTrace();}}log.debug("等到了它的早餐");} 
finally {lock.unlock();}}).start();sleep(1);sendBreakfast();sleep(1);sendCigarette();}private static void sendCigarette() {lock.lock();try {log.debug("送烟来了");hasCigrette = true;waitCigaretteQueue.signal();} 
finally {lock.unlock();}}private static void sendBreakfast() {lock.lock();try {log.debug("送早餐来了");hasBreakfast = true;waitbreakfastQueue.signal();} 
finally {lock.unlock();}}

输出

18:52:27.680 [main] c.TestCondition - 送早餐来了 
18:52:27.682 [Thread-1] c.TestCondition - 等到了它的早餐 
18:52:28.683 [main] c.TestCondition - 送烟来了 
18:52:28.683 [Thread-0] c.TestCondition - 等到了它的烟 
http://www.hkea.cn/news/858210/

相关文章:

  • 网站 色彩武汉it培训机构排名前十
  • 怎么做资源网站网络培训中心
  • 服装品牌网站建设营销网站建设选择原则
  • 乌鲁木齐新市网站建设有哪些网络营销公司
  • 网站的后台怎么做企业网络规划设计方案
  • 做网站文字字号大小企业网站设计要求
  • ae有么有做gif的网站品牌推广方案范文
  • apicloud官网下载seo关键词优化排名公司
  • 上海网站制作福州百度关键字优化精灵
  • 做uml图网站百度账号快速注册入口
  • 广西梧州南京 seo 价格
  • 网站警察备案seo关键词优化平台
  • 网站开发设计实训 报告惠州网站建设
  • 网站开发的原理山西免费网站关键词优化排名
  • 石家庄网站建设全包免费推广网站2024
  • 阿里云网站备案时间无锡seo网站管理
  • 景点介绍网站模板重庆百度关键词推广
  • 做亚马逊网站费用吗曲靖新闻今日头条
  • bing 网站管理员2023今日新闻头条
  • 深圳市做网站前十强百度一下搜索网页
  • 做执法设备有哪些网站国家免费培训学校
  • 顺德乐从有做阿里巴巴的网站吗杭州网站设计
  • 做英文网站 用阿里服务器行吗b2b网站推广排名
  • 搭建网站做淘宝客网赌怎么推广拉客户
  • 网站建设前台与后台最新技术2021最新免费的推广引流软件
  • 做网站基本语言淘宝如何提升关键词排名
  • wordpress怎样分类目录添加标签seo文章范文
  • 订阅号可以做网站吗南宁seo外包服务商
  • 邢台哪儿做网站便宜宁波 seo排名公司
  • 深圳网站优化咨询网上广告怎么推广