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

网站开发与软件开发区别湖北seo整站优化

网站开发与软件开发区别,湖北seo整站优化,怎么自学互联网技术,做网站哪里最好目录 1.前言 2.正文 2.1悲观锁和乐观锁 2.2重量级锁和轻量级锁 2.3挂起等待锁和自旋锁 2.4互斥锁与读写锁 2.5可重入锁与不可重入锁 2.6公平锁与不公平锁 2.7synchronized优化 2.7.1锁升级 2.7.2锁消除 2.7.3锁粗化 3.小结 1.前言 哈喽大家好,今天来给…


目录

1.前言

2.正文

2.1悲观锁和乐观锁

2.2重量级锁和轻量级锁

2.3挂起等待锁和自旋锁

2.4互斥锁与读写锁

2.5可重入锁与不可重入锁

2.6公平锁与不公平锁

2.7synchronized优化

2.7.1锁升级

2.7.2锁消除

2.7.3锁粗化

 3.小结


1.前言

哈喽大家好,今天来给大家分享Java多线程中常见的锁策略,锁策略不是和Java强相关,但凡涉及到并发编程涉及到锁都会涉及锁策略,概念较多但都很重要,废话不多说让我们开始吧。

2.正文

首先在这里声明一点:以下讲的各种锁,不是针对某一种具体的锁,而是某个具体锁具有“悲观"特性或者“乐观”等特性~~

2.1悲观锁和乐观锁

悲观锁

  • 定义:假设并发冲突一定会发生,因此在操作数据前先加锁,确保同一时刻只有一个线程能访问资源。

  • 特点:强一致性,但性能开销大。

乐观锁

  • 定义:假设并发冲突很少发生,操作数据时不加锁,只在提交修改时检查是否被其他线程修改过。

  • 特点:高性能,但可能需重试。


悲观锁的现实场景

  • 你去银行取钱,柜员会说:"稍等,我先锁上保险箱再给你拿钱。"

  • 为什么?银行默认你会和别人争抢取钱这个操作,必须锁住资源。

乐观锁的现实场景

  • 你和同事改同一份Docs,直接编辑,保存时系统提示:"有冲突,请解决。"

  • 为什么?默认你们不会同时改同一段落,冲突了再处理。

根本区别在于对接下来锁竞争的是否激烈。


对比维度悲观锁乐观锁
默认态度"肯定会有人抢,先锁再说!""应该没人抢,冲突了再说~"
实现方式synchronizedReentrantLock版本号、CAS(如AtomicInteger
性能开销高(上下文切换、阻塞)低(无阻塞,可能重试)
适用场景写多读少(如支付、转账)读多写少(如商品库存、点赞计数)
失败处理线程阻塞等待回滚或自动重试

2.2重量级锁和轻量级锁

重量级锁

  • 定义:依赖操作系统内核的互斥量(Mutex Lock)实现的锁机制,线程竞争时会直接进入阻塞状态,由操作系统负责线程调度。

  • 特点:功能完备(支持公平性、超时等),但性能开销大(涉及用户态到内核态的切换)。

轻量级锁

  • 定义:基于CAS(Compare-And-Swap)自旋实现的锁机制,线程通过循环尝试获取锁,避免直接进入阻塞状态。

  • 特点:性能高(无系统调用),但长时间自旋会浪费CPU资源。


重量级锁的现实场景

  • 你去医院挂号,发现窗口排队的人很多,直接去休息区睡觉(线程阻塞),等护士叫号(操作系统唤醒)。

  • 为什么?因为你知道要等很久,不如让出资源。

轻量级锁的现实场景

  • 你在便利店排队结账,发现前面只有一个人,于是站在原地不停张望(自旋),等对方结束立马抢位置。

  • 为什么?因为等待时间短,不值得去找座位。


  • 重量级锁,当悲观的场景下,此时就要付出更多的代价。(更低效)
  • 轻量级锁,应对乐观的场景,此时付出的代价就会更小。(更高效)

对比维度重量级锁轻量级锁
实现原理通过操作系统内核的互斥量(Mutex)用户态的CAS自旋(如AtomicInteger
线程状态阻塞(挂起)运行中(自旋等待)
性能开销高(上下文切换约1-10μs)低(自旋耗时约0.1-1ns/次)
适用场景高竞争、长临界区低竞争、短临界区
失败处理线程进入等待队列继续自旋或升级为重量级锁

2.3挂起等待锁和自旋锁

挂起等待锁就是重量级锁的典型实现,而自旋锁就是轻量级锁的典型实现。

挂起等待锁(阻塞锁)

  • 定义:当线程获取锁失败时,立即释放CPU资源,进入阻塞状态(挂起),等待被唤醒

  • 核心机制:依赖操作系统调度,涉及线程上下文切换

  • 典型实现:Java的synchronized在重量级锁状态、ReentrantLock.lock()

自旋锁

  • 定义:当线程获取锁失败时,不放弃CPU,而是循环重试(自旋),直到成功获取锁

  • 核心机制:通过CPU空转(忙等待)避免上下文切换

  • 典型实现:Java的AtomicIntegerCAS操作、ReentrantLock.tryLock()自旋版本(以后会详细讲解Java中的CAS)


挂起等待锁场景

  • 你去热门餐厅取号,服务员说:"现在没位,去旁边商场逛2小时再回来"(线程挂起)

  • 为什么合理:等待时间长时,干等着(自旋)反而浪费精力

自旋锁场景

  • 你在便利店排队,收银员说:"稍等1分钟马上好",你选择站着玩手机等待(自旋)

  • 为什么合理:短暂等待时,来回走动(上下文切换)更耗能


对比维度挂起等待锁自旋锁
等待机制立即释放CPU进入阻塞状态保持CPU占用循环检测
系统开销高(上下文切换约1-10μs)低(但浪费CPU周期)
实现复杂度高(需OS支持线程调度)低(CAS即可实现)
适用场景锁持有时间长(>1ms)锁持有时间短(<1μs)
线程状态BLOCKED/WATINGRUNNABLE
公平性通常可实现公平通常是非公平的
典型应用数据库事务、文件IO计数器、状态标志

2.4互斥锁与读写锁

分析下这个读写锁:多个线程读取一个数据,是本身就线程安全的。多个线程读取,一个线程修改,肯定会涉及到线程安全问题。如果你把读和写都加上普通的互斥锁,意味着锁冲突将会非常严重,读锁和读锁之间不互斥,读锁和写锁互斥,写锁和写锁之间也互斥。于是乎读写所的存在,保证线程安全的前提下,降低锁冲突概率提高效率。


互斥锁(Mutex Lock)

  • 定义:独占锁,同一时刻只允许一个线程访问共享资源

  • 特点:强排他性,读/写操作同等对待

  • 典型实现:Java的synchronizedReentrantLock

读写锁(ReadWrite Lock)

  • 定义:分离锁,将读操作和写操作区别对待

  • 特点:允许多个读线程并发,写线程独占

  • 典型实现:Java的ReentrantReadWriteLock


互斥锁场景

  • 图书馆自习室规则:"每次只允许一人进入,无论你是看书(读)还是做笔记(写)"

  • 结果:即使多人只想看书,也得排队轮流进

读写锁场景

  • 改进后的规则:"看书的人可以一起进,但做笔记的人必须单独使用房间"

  • 结果:读书效率提升,写作时仍保证独占


对比维度互斥锁读写锁
并发粒度完全互斥读读并发,读写/写写互斥
吞吐量低(所有操作串行)高(读操作可并行)
实现复杂度简单复杂(需维护读/写状态)
适用场景读写操作耗时相近读多写少(≥5:1)
线程饥饿风险写线程可能被读线程长期阻塞
锁升级不支持读锁不能升级为写锁(会死锁)
公平性可公平/非公平可公平/非公平

2.5可重入锁与不可重入锁

之前文章中讲解过这里不过多展开了喔~简单总结~


可重入锁(Reentrant Lock)

  • 定义:同一个线程可以多次获取同一把锁,锁会维护一个持有计数(hold count)

  • 关键特性:防止线程自己造成死锁

  • 典型实现:Java的synchronizedReentrantLock

不可重入锁(Non-reentrant Lock)

  • 定义:线程获取锁后,再次尝试获取会立即阻塞/失败

  • 关键特性:严格线性获取锁

  • 典型实现:早期的简单锁实现、某些特定场景的自旋锁


可重入锁场景

  • 你家大门装了智能锁,你(线程)进入时:

  1. 第一次进门:验证指纹(获取锁)
  2. 进卧室时:不再验证(重入计数+1)
  3. 离开卧室:不真正锁门(计数-1)
  4. 最终出门:才真正上锁(计数归零)

不可重入锁场景

  • 老式钥匙锁的尴尬情况:

  1. 你进门后锁上门(获取锁)
  2. 想进里屋时发现需要钥匙(再次获取锁)
  3. 钥匙插在外门锁上(死锁形成)
  4. 最终困在门厅里(线程阻塞)

对比维度可重入锁不可重入锁
死锁预防避免同一线程自我死锁可能因递归调用导致自我死锁
实现复杂度高(需维护线程ID和计数)低(只需布尔状态)
性能开销略高(计数器操作)略低
适用场景递归调用、回调函数简单线性流程
锁释放必须完全释放(计数归零)单次解锁即释放
典型应用Java同步机制、数据库事务某些内核锁、特殊优化场景

2.6公平锁与不公平锁

公平锁(Fair Lock)

  • 定义:按照线程请求锁的先后顺序分配锁,遵循FIFO(先进先出)原则

  • 特点:避免线程饥饿,保证公平性

  • 实现方式:通过队列维护等待线程(如ReentrantLock(true)

非公平锁(Non-fair Lock)

  • 定义:允许线程插队获取锁,不保证请求顺序

  • 特点:吞吐量高,但可能导致线程饥饿

  • 实现方式:直接尝试CAS获取锁(如synchronizedReentrantLock()默认模式)


公平锁场景

  • 银行VIP窗口叫号系统:"请A001号到3号窗口"(严格按取号顺序服务)

  • 优点:先来的人一定能先办业务

  • 缺点:即使窗口空闲,也必须叫号

非公平锁场景

  • 地铁早高峰排队:"车门一开,所有人挤着上车"(谁快谁上)

  • 优点:车厢利用率高(减少空置时间)

  • 缺点:可能有人永远挤不上去


对比维度公平锁非公平锁
排队机制严格FIFO允许插队(新线程可直接竞争)
吞吐量较低(约降低30%)较高
线程饥饿不会发生可能发生
实现复杂度高(需维护等待队列)低(直接CAS)
响应时间稳定但较长不稳定(可能极快或极慢)
适用场景交易系统、计费系统高并发缓存、计数器
JVM实现ReentrantLock(true)synchronizedReentrantLock()

公平锁:

public class FairLockDemo {private static final ReentrantLock lock = new ReentrantLock(true); // 公平模式public static void main(String[] args) {for (int i = 0; i < 3; i++) {new Thread(() -> {lock.lock();try {System.out.println(Thread.currentThread().getName() + "获取锁");} finally {lock.unlock();}}, "Thread-" + i).start();}}
}
// 输出保证按线程启动顺序获取锁

非公平锁:

public class NonFairDemo {private static final ReentrantLock lock = new ReentrantLock(); // 默认非公平public static void main(String[] args) {// 先让主线程持有锁lock.lock();new Thread(() -> {System.out.println("子线程尝试获取锁");lock.lock();  // 这里会插队!System.out.println("子线程获取成功");lock.unlock();}).start();Thread.sleep(100); // 确保子线程启动System.out.println("主线程释放锁");lock.unlock();  // 释放后子线程可能抢到,即使有其他等待线程}
}

2.7synchronized优化

2.7.1锁升级

JVM根据竞争情况,动态调整synchronized的锁状态,从低开销到高开销逐步升级,避免一刀切使用重量级锁。 JVM没有提供锁降级。

graph LRA[无锁] -->|首次获取| B[偏向锁]B -->|有竞争| C[轻量级锁]C -->|竞争加剧| D[重量级锁]
  1. 偏向锁(Biased Locking)

    • 场景:单线程反复访问同步块

    • 原理:在对象头记录线程ID(无需CAS)

  2. 轻量级锁(Thin Lock)

    • 场景:多线程交替执行(无真正竞争)

    • 原理

      • 栈帧中创建Lock Record

      • 通过CAS将对象头指向Lock Record

  3. 重量级锁(Heavyweight Lock)

    • 场景:高并发竞争

    • 原理:通过ObjectMonitor实现

    • 开销:上下文切换约1-10μs


补充以下何为偏向锁:
刚一上来,不是真加锁, 而是只是简单做一个标记,进行synchronized。这个标记,非常轻量, 相比于加锁解锁来说,效率高很多~如果没有其他线程来竞争这个锁,最终当前线程执行到解锁代码,也就只是简单清除上标记即可~~(不涉及真加锁,真解锁)如果有其他线程来竞争,就抢先一步,在另一个线程拿到锁之前,抢先拿到锁真假锁了,偏向锁 =>轻量级锁,其他线程只能阻塞等待。

2.7.2锁消除

这也是编译器优化的一种体现。


概念:编译器会判定,当前这个代码逻辑是否真的需要加锁,如果确实不需要加锁,但是你写了 synchronized,,就会自动把synchronized给去掉,像一些判定不清楚的情况,不会触发锁消除。

如果到处有synchronized,意味着优化机制,只能把其中一部分,他能明确判定的给优化掉,还会有很多不应该使用, 但是编译器也优化不调。

2.7.3锁粗化

概念
将相邻的多个细粒度锁合并为单个大锁,减少锁申请/释放开销。(加锁和解锁之间,包含的代码越多,就认为锁的粒度就越粗)

触发场景

// 原始代码
for (int i = 0; i < 100; i++) {synchronized(obj) { // 每次循环都加锁doSomething();}
}// 优化后等效代码
synchronized(obj) { // 合并为单个锁for (int i = 0; i < 100; i++) {doSomething();}
}

以上三种做个总结:

优化手段适用场景性能提升幅度实现层级
锁升级所有synchronized场景10-100倍JVM运行时
锁消除线程私有对象2-5倍JIT编译期
锁粗化密集短锁操作1.5-3倍字节码优化阶段

 3.小结

今天的分享到这里就结束了,喜欢的小伙伴点点赞点点关注,你的支持就是对我最大的鼓励,大家加油!

http://www.dtcms.com/wzjs/415604.html

相关文章:

  • 医院网站怎么做优化排名靠前淘宝店铺推广方式有哪些
  • 一个人 建设网站微信crm客户管理系统
  • 事业单位网站登录模板网站搭建详细教程
  • 推荐家居网站建设百度大数据中心
  • 北京做商铺的网站百度代理查询系统
  • 广州网站建设 易企建站广州排名推广
  • 网站推广工作长沙网络推广公司
  • 重庆沙坪坝企业网站建设联系电话石家庄新闻
  • 动漫设计与游戏制作专业优化培训课程
  • 企业网站导航下拉菜单怎么做关键词排名查询工具有什么作用?
  • 青海中小企业网站建设企查查在线查询
  • thinkphp企业网站系统长沙百家号seo
  • 怎么建设菠菜网站网站如何做seo排名
  • 网站优化图片济南做网站公司哪家好
  • 淘宝做店招的网站专业做网站建设的公司
  • 网站加友情链接上海公布最新情况
  • 陕西省住房建设厅网站百度seo推广计划类型包括
  • 做新闻源网站采集站赚钱全国十大婚恋网站排名
  • 郑州市汉狮做网站免费模式营销案例
  • 福州做网站费用搜索引擎优化百度百科
  • 绍兴网站建设设计制作推广平台怎么做
  • 网站 字号 英文上海百度推广优化
  • 有什么网站可以做外贸出口信息实体店100个营销策略
  • 郑州网站开发比较好的网络公司阿里云官网首页
  • 国外开源 企业网站电子商务网站建设的步骤
  • 什么是网站开发网址检测
  • 买好域名后怎么做网站搜索引擎网站大全
  • 企业安全文化建设seo怎么优化排名
  • wordpress 备案信息修改东莞百度快速排名优化
  • 网站搜索怎么做的我想学做互联网怎么入手