解密Java中神奇的Synchronized关键字
文章目录
- 🎉 定义
- 🎉 JDK6以前
- 🎉 偏向锁和轻量级锁
- 📝 偏向锁
- 📝 轻量级锁
- 📝 自旋锁
- 📝 重量级锁
- 🔥 1. 加锁
- 🔥 2. 等待
- 🔥 3. 撤销
- 🎉 锁优化
- 📝 锁消除
- 📝 锁粗化
- 📝 自适应自旋
- 🎉 synchronized关键字的用法和注意事项
- 📝 修饰方法
- 📝 修饰代码块
- 📝 修饰静态方法
- 📝 修饰类
📕我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。🌎跑过十五公里、徒步爬过衡山、🔥有过三个月减肥20斤的经历、是个喜欢躺平的狠人。
📘拥有多年一线研发和团队管理经验,研究过主流框架的底层源码(Spring、SpringBoot、Spring MVC、SpringCould、Mybatis、Dubbo、Zookeeper),消息中间件底层架构原理(RabbitMQ、RockerMQ、Kafka)、Redis缓存、MySQL关系型数据库、 ElasticSearch全文搜索、MongoDB非关系型数据库、Apache ShardingSphere分库分表读写分离、设计模式、领域驱动DDD、Kubernetes容器编排等。🎥有从0到1的高并发项目经验,利用弹性伸缩、负载均衡、报警任务、自启动脚本,最高压测过200台机器,有着丰富的项目调优经验。
📙经过多年在CSDN创作上千篇文章的经验积累,我已经拥有了不错的写作技巧。同时,我还与清华大学出版社签下了四本书籍的合约,并将陆续在明年出版。这些书籍包括了基础篇、进阶篇、架构篇的📌《Java项目实战—深入理解大型互联网企业通用技术》📌,以及📚《解密程序员的思维密码–沟通、演讲、思考的实践》📚。具体出版计划会根据实际情况进行调整,希望各位读者朋友能够多多支持!

希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: 我是廖志伟
- 👉开源项目:java_wxid
- 🌥 哔哩哔哩:我是廖志伟
- 🎏个人社区:幕后大佬
- 🔖个人微信号:
SeniorRD
💡在这个美好的时刻,本人不再啰嗦废话,现在毫不拖延地进入文章所要讨论的主题。接下来,我将为大家呈现正文内容。


在Java中,当多个线程同时访问同一块代码,会产生竞态条件,可能会导致数据不一致或其他问题。为了解决这个问题,Java提供了synchronized关键字,它能够保证同一时刻被synchronized修饰的代码最多只有1个线程执行。本文将从synchronized的定义、JDK6以前的实现方式、偏向锁和轻量级锁、锁优化、synchronized关键字的用法和注意事项等方面详细讲解。
🎉 定义
在Java中,synchronized关键字是一种同步锁,在多线程编程中,用于解决多个线程同时访问同一个资源的问题。当一个线程持有锁时,其他线程将会被阻塞,直到当前线程释放锁为止。synchronized可以加在方法上或对象上,作用的对象是非静态的,则取得的锁是对象锁;作用的对象是静态方法或类,则取到的锁是类锁,这个类所有的对象用的是同一把锁。
🎉 JDK6以前
在JDK6以前,synchronized加锁是通过对象内部的监视器锁来实现的,监视器锁本质上又是依赖于底层的操作系统的Mutex Lock来实现的,因此在高并发情况下,synchronized的性能就会变得非常低下。
当多个线程争夺同一个锁时,会发生线程阻塞和唤醒的操作,这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要比较长的时间,导致程序执行效率低下。
🎉 偏向锁和轻量级锁
为了提高synchronized的效率,JDK6引入了偏向锁和轻量级锁。
📝 偏向锁
在Java中,同步操作需要获取锁来保证多个线程访问共享资源的安全性。而在锁的获取过程中,JVM添加了一种优化方式——偏向锁。当一个线程访问同步块时,如果这个同步块没有被其他线程占用,那么JVM会把这个同步块的锁标记为偏向锁,并把当前线程ID记录在MarkWord中。这样,下次同一线程访问同步块时,就不需要再次获取锁,直接进入同步块即可。
但是,当有其他线程来竞争锁的时候,偏向锁需要进行撤销,转而使用轻量级锁或者重量级锁来保证同步操作的安全性。这里给出一个对象从无锁到偏向锁转化的过程:
第一步,检测MarkWord是否为可偏向状态,即锁标识位是01,如果是,则说明当前对象可被偏向,可以执行同步代码块。
第二步,如果需要访问同步块的线程ID与MarkWord中记录的线程ID相同,则不需要进行竞争,直接执行同步代码块即可。
第三步,如果需要访问同步块的线程ID与MarkWord中记录的线程ID不同,说明该对象已经被其他线程占用,需要进行竞争。此时,JVM会进行CAS操作,如果操作成功,则将线程ID替换为当前线程ID,并执行同步代码块。
第四步,如果CAS操作失败,则需要进行偏向锁的撤销。这个过程可以有两种情况触发:一是对象头的Epoch字段计数到一定次数,二是多个线程尝试竞争该对象的锁,都失败了。
第五步,完成偏向锁的撤销后,持有偏向锁的线程不会被挂起,继续执行同步代码块。如果获取锁失败,则视情况进行自旋或者进行阻塞等待,进一步升级为轻量级锁或重量级锁。
需要注意的是,在偏向锁撤销的过程中,需要清除那些曾经持有该偏向锁对象的线程的锁记录。这是因为在偏向锁状态下,持有锁的线程会在对象头中记录一个标记位和持有该锁的线程ID。而在撤销偏向锁的过程中,需要清除这些锁记录,因为它们已经不再持有该锁,以便其他线程可以重新争夺锁的所有权。并且,偏向锁撤销的过程不一定会挂起所有持有偏向锁的线程,只有在线程竞争锁时才会挂起线程。
在偏向锁撤销过程中,JVM会启动偏向锁撤销线程来遍历所有持有该偏向锁对象的线程栈,清除它们的锁记录。而在多线程编程中,当多个线程对一个内存位置进行读取和修改时,可能会出现一种情况——ABA问题。为了解决这个问题,JVM 在对象的内存布局中添加了一个Epoch字段,来判断一个线程是否因为ABA问题导致的线程变化。这个Epoch字段并不直接关系到偏向锁撤销的过程,但是有助于判断锁的状态是否发生了变化。
在实际的应用中,偏向锁的优化方式能够显著提高同步代码块的性能,但它并不适用于所有场景。在多线程应用程序中,如果存在大量的锁竞争,那么偏向锁的优化效果会下降,甚至被轻量级锁或重量级锁取代。因此,在使用偏向锁的时候,需要根据具体情况进行考虑和使用。同时,了解偏向锁的撤销过程,有助于我们更好地理解同步机制的底层实现,更好地进行多线程编程。
📝 轻量级锁
轻量级锁升级过程是为了实现对象的互斥访问,首先在当前线程的栈帧中创建一个锁记录用于存储锁对象的MarkWord的拷贝。该拷贝无锁状态对象头中的MarkWord,用于在申请对象锁时作为CAS的比较条件。同时也能通过这个比较判定是否在持有锁的过程中,这个锁被其他线程申请过,如果有,在释放锁的时候要唤醒被挂起的线程。轻量级锁的MarkWord如果存有hashCode,解锁后也需要恢复。拷贝成功后,虚拟机使用CAS操作把对象中对象头的MarkWord替换为指向锁记录的指针,再把锁记录空间里的owner指针指向加锁的对象。如果这个更新操作成功,那么当前线程就拥有了该对象的锁,并且对象MarkWord的锁标志位设置为“00”,表示此对象处于轻量级锁定状态。
如果更新操作失败,虚拟机会检查对象的MarkWord中的Lock Word是否指向当前线程的栈帧。如果是,则当前线程已经拥有了这个对象的锁,可以直接进入同步块继续执行。如果不是,则说明多个线程竞争锁,要进入自旋。若自旋结束时依然未获得锁,轻量级锁就要升级为重量级锁,锁标志的状态值变为“10”,对象MarkWord中存储的就是指向重量级锁(互斥量)的指针,当前线程以及后续等待锁的线程也要进入阻塞状态。
当锁升级为轻量级锁后,如果依然有新线程过来竞争锁,首先新线程会自旋尝试获取锁,尝试到一定次数(默认10次)依然没有拿到,锁就会升级成重量级锁。一般来说,同步代码块内的代码应该很快就执行结束,这时线程B自旋一段时间是很容易拿到锁的。但如果不巧,没能拿到锁,自旋就会成为死循环,并且耗费CPU。因此,虚拟机会直接将锁升级为重量级锁,不再进行自旋。这样就不需要了线程一直自旋,性能会得到很大的提升。
📝 自旋锁
自旋锁并不是一种锁状态,而是一种智能的线程同步策略。它可以用于保护临界区的并发访问,避免多个线程同时进入临界区导致的数据不一致问题。自旋锁的核心思想是,在等待锁的过程中,不会主动阻塞线程,而是继续执行当前线程内的代码,同时不断自旋等待锁的释放,以减少线程的阻塞和唤醒,提高并发性能。
当一个线程尝试获取某个锁时,如果发现该锁已经被其他线程占用,则该线程不会被立即挂起或者睡眠,而是开始自旋等待锁的释放。自旋等待期间,该线程会一直占用CPU处理器资源,循环检测锁是否被释放。自旋等待不能替代阻塞,因为如果自旋时间过长,会占用过多CPU资源,反而降低性能。
自旋锁适用于维护临界区很小的情况。临界区很小表示锁占用的时间很短,如果持有锁的线程很快就能释放锁,那么自旋的效率就会非常高。但是自旋的次数必须要有一个限度,如果自旋超过了定义的次数仍然没有获取到锁,就应该被挂起。然而这个限度不能固定,因为程序锁的状况是不可预估的,所以JDK1.6引入了自适应的自旋锁,可以根据程序运行的情况动态调整自旋的次数。比如如果线程自旋成功了,那么下次自旋的次数会更多,反之则会更少,从而避免了自旋等待过程中浪费处理器资源的情况。
要开启自旋锁,可以使用JDK1.6之后提供的参数–XX:+UseSpinning,如果需要修改自旋次数,可以使用–XX:PreBlockSpin参数来指定,其中默认值为10次。使用自旋锁可以在一定程度上提高多线程程序的性能,但也需要注意合理设置自旋次数和使用范围,以免造成过多的CPU资源占用和线程的饥饿等问题。
📝 重量级锁
重量级锁是Java中的一种锁,是通过对象内部的监视器锁(Monitor)来实现的。监视器锁本质上又是依赖于底层的操作系统的MutexLock来实现的。由于操作系统实现线程之间的切换需要从用户态转换到核心态,状态之间的转换需要比较长的时间,因此依赖于操作系统MutexLock所实现的锁我们称之为“重量级锁”。
当一个线程在等待锁时,会不停的进行自旋,其中自旋的线程数达到CPU核数一半之后,就会升级为重量级锁。在升级为重量级锁之后,锁标志会被置为10,同时将MarkWord中的指针指向重量级的Monitor,这将阻塞所有没有获取到锁的线程。
重量级锁的加锁-等待-撤销流程分为三个步骤。
🔥 1. 加锁
当一个线程请求锁时,首先会查看锁标志是否为0,如果为0,则表示锁没有被占用,此时该线程会将锁标志置为1,并且获取到锁。如果锁标志不为0,则表示锁已经被占用,此时该线程会进入自旋状态。
🔥 2. 等待
在自旋状态下,如果锁一直没有被释放,那么自旋的线程数量会不断增加。当自旋的线程数量达到CPU核数的1/2时,就会升级为重量级锁。在升级为重量级锁之后,会将锁标志置为10,同时将MarkWord中的指针指向重量级的Monitor,这将阻塞所有没有获取到锁的线程。
🔥 3. 撤销
当一个线程释放锁时,会将锁标志置为0。此时正在等待的线程会被唤醒并争夺锁,曾经获得过锁的线程,在被唤醒之后会优先得到锁。如果一个线程在等待锁的过程中调用了wait()方法,则该线程会被加入到等待队列中,并通过wait_set等待被唤醒。如果一个线程在等待锁的过程中调用了notify()方法,则该线程会将等待队列中的第一个线程唤醒,等待队列中被唤醒的线程会被加入到同步队列中,并通过park()方法等待获取锁。
当重量级锁撤销之后,系统会将其转变为无锁状态。撤销锁之后会清除创建的Monitor对象,并修改markword,这个过程需要一段时间。Monitor对象是通过GC来清除的。当GC清除掉Monitor对象之后,锁就被撤销为无锁状态。
重量级锁适用于多线程互斥访问同一资源的情况。由于重量级锁性能较低,因此只在必要时才应该使用。在Java中,Synchronized关键字就是一种重量级锁。在使用Synchronized关键字时,应尽量减少锁的持有时间,这样可以提高程序的并发性能。
🎉 锁优化
针对于synchronized的性能问题和在某些情况下可能导致死锁的情况,Java提供了以下的锁优化:
📝 锁消除
在编译器层面消除不必要的加锁操作,将锁的范围缩小到最小,这样可以减少锁竞争的概率,提高程序的执行效率。
📝 锁粗化
在进行一系列操作时,将多个连续的加锁操作放在一个代码块中,这样可以减少加锁和解锁的开销,提高程序的执行效率。
📝 自适应自旋
当线程尝试获取同步锁失败后,它并不会立即进入阻塞状态,而是再次尝试获取同步锁,如果一段时间内失败的次数越多,就会进入阻塞状态。这个时间段就是自旋时间,是由操作系统动态调整的。
🎉 synchronized关键字的用法和注意事项
synchronized关键字的用法有以下几种:
📝 修饰方法
这种方式是修饰整个方法,即使方法中没有同步代码块,也会锁定这个方法,这种方式适用于整个方法需要同步的情况。
public synchronized void method() {// 同步代码块
}
📝 修饰代码块
这种方式是将同步代码块包在synchronized括号内,只有在执行到synchronized代码块时才会锁定,这种方式适用于只需要同步执行部分代码的情况。
public void method() {synchronized (this) {// 同步代码块}
}
📝 修饰静态方法
和修饰方法类似,这种方式是锁定整个静态方法,适用于整个静态方法需要同步的情况。
public synchronized static void method() {// 同步代码块
}
📝 修饰类
这种方式是锁定整个类,即使不同实例中的线程也会被锁定,适用于整个类需要同步的情况。
public void method() {synchronized (ClassName.class) {// 同步代码块}
}
需要注意的是,只有在多个线程访问同一块资源时,才需要使用synchronized关键字。如果同步块内的代码很少,那么锁的代价就会超过同步块内的代码的执行代价,从而导致程序执行效率变低。同时,在使用synchronized关键字时,需要考虑死锁问题,即多个线程无限制地等待对方释放锁的情况。因此,在编写代码时,需要特别注意同步块的范围和锁的粒度。

🔔如果您需要转载或者搬运这篇文章的话,非常欢迎您私信我哦~
希望各位读者大大多多支持用心写文章的博主,现在时代变了,信息爆炸,酒香也怕巷子深,博主真的需要大家的帮助才能在这片海洋中继续发光发热,所以,赶紧动动你的小手,点波关注❤️,点波赞👍,点波收藏⭐,甚至点波评论✍️,都是对博主最好的支持和鼓励!
- 💂 博客主页: 我是廖志伟
- 👉开源项目:java_wxid
- 🌥 哔哩哔哩:我是廖志伟
- 🎏个人社区:幕后大佬
- 🔖个人微信号:
SeniorRD
📥博主的人生感悟和目标

- 🍋程序开发这条路不能停,停下来容易被淘汰掉,吃不了自律的苦,就要受平庸的罪,持续的能力才能带来持续的自信。我本身是一个很普通程序员,放在人堆里,除了与生俱来的盛世美颜,就剩180的大高个了,就是我这样的一个人,默默写博文也有好多年了。
- 📺有句老话说的好,牛逼之前都是傻逼式的坚持,希望自己可以通过大量的作品、时间的积累、个人魅力、运气、时机,可以打造属于自己的技术影响力。
- 💥内心起伏不定,我时而激动,时而沉思。我希望自己能成为一个综合性人才,具备技术、业务和管理方面的精湛技能。我想成为产品架构路线的总设计师,团队的指挥者,技术团队的中流砥柱,企业战略和资本规划的实战专家。
- 🎉这个目标的实现需要不懈的努力和持续的成长,但我必须努力追求。因为我知道,只有成为这样的人才,我才能在职业生涯中不断前进并为企业的发展带来真正的价值。在这个不断变化的时代,我必须随时准备好迎接挑战,不断学习和探索新的领域,才能不断地向前推进。我坚信,只要我不断努力,我一定会达到自己的目标。
相关文章:
解密Java中神奇的Synchronized关键字
文章目录 🎉 定义🎉 JDK6以前🎉 偏向锁和轻量级锁📝 偏向锁📝 轻量级锁📝 自旋锁📝 重量级锁🔥 1. 加锁🔥 2. 等待🔥 3. 撤销 🎉 锁优化…...
微信删除的好友还能找回来吗?盘点5种超实用的方法!
当我们在认识新的朋友时,都喜欢通过添加对方微信来保持日后的联系。但是有时候可能会由于没有及时备注而不小心误删了对方。想要将对方加回来,又找不到有效的方法。微信删除的好友还能找回来吗?当然可以了!但我们要根据实际情况选…...
Nmap 常用命令汇总
Nmap 命令格式 namp 【扫描类型】 选项 {目标ip 或 目标网络段} 根据扫描类型,可分成两类,一种是主机扫描类型,另一种是端口扫描类型 一、常用主机扫描: 扫描类型: -PR 对目标ip所在局域网进行扫描 (使…...
谷歌浏览器最新版和浏览器驱动下载地址
谷歌最新版和驱动下载地址...
[游戏开发][Unity]Unity运行时加载不在BuildSetting里的场景
从Assets开始路径要写全,需要.unity扩展名 如果路径写错了会报错 LoadSceneAsyncInPlayMode expects a valid full path. The provided path was Assets/Works/Resource/Scenes.unity string sceneFullPath "Assets/Works/Resource/Scenes/TestScene.unity…...
flutter开发实战-hero动画简单实现
flutter开发实战-hero动画简单实现 使用Flutter的Hero widget创建hero动画。 将hero从一个路由飞到另一个路由。 将hero 的形状从圆形转换为矩形,同时将其从一个路由飞到另一个路由的过程中进行动画处理。 Flutter Hero动画 Hero 指的是可以在路由(页面)之间“飞行”的 widge…...
Spring Boot + EasyUI 创建第一个项目(一)
创建一个Spring Boot和EasyUI相结合的项目。 一、构建一个Spring Boot项目 Spring Boot之创建一个Spring Boot项目(一)-CSDN博客 二、配置Thymeleaf Spring Boot Thymeleaf(十一)_thymeleaf 设置字体_人……杰的博客-CSDN博客…...
短视频矩阵系统源码/技术应用搭建
短视频矩阵系统开发围绕的开发核心维度: 1. 多账号原理开发维度 适用于多平台多账号管理,支持不同类型账号矩阵通过工具实现统一便捷式管理。(企业号,员工号,个人号) 2. 账号矩阵内容开发维护 利用账号矩…...
硬核子牙:我准备写一本《带你手写64位多核操作系统》的书!
哈喽,我是子牙,一个很卷的硬核男人 深入研究计算机底层、Windows内核、Linux内核、Hotspot源码……聚焦做那些大家想学没地方学的课程。为了保证课程质量及教学效果,一年磨一剑,三年先后做了三个课程:手写JVM、手写OS…...
c++访问修饰符与继承关系
前言 C提供了三个修饰符来限定类成员的被访问权限,分别是public、protected、private。通过限定访问权限,可以达到程序编写者想要解决的安全问题和权限问题。这种权限的设置对于安全是非常必要的。 不同修饰下的类成员被访问权限 类成员默认访问权限为…...
【RTOS学习】事件组 | 任务通知
🐱作者:一只大喵咪1201 🐱专栏:《RTOS学习》 🔥格言:你只管努力,剩下的交给时间! 事件组 | 任务通知 🚁事件组🛴大概原理🛴使用事件组的函数同步…...
【TES605】基于Virtex-7 FPGA的高性能实时信号处理平台
板卡概述 TES605是一款基于Virtex-7 FPGA的高性能实时信号处理平台,该平台采用1片TI的KeyStone系列多核DSP TMS320C6678作为主处理单元,采用1片Xilinx的Virtex-7系列FPGA XC7VX690T作为协处理单元,具有2个FMC子卡接口,各个处理节…...
Java Azure开发 使用已有token字符串创建GraphServiceClient
一、背景说明 在已有的项目中,已经获取到了Graph的AccessToken并保存在内存里面。所以不希望再通过client secret或者certificate去创建GraphServiceClient对象。希望使用现有的token字符串来创建初始化创建GraphServiceClient从而来实现Graph其他API功能。 二、具体…...
【Qt】消息机制和事件
文章目录 事件event()事件过滤器案例:检测鼠标事件案例:定时器 事件 事件(event)是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘,或者是窗口需要重新绘制的时候,都会发出一个相应的事…...
爬虫模拟用户登录
使用爬虫模拟用户登录过程一般包括以下几个步骤: 导入所需的库:一般需要导入requests和BeautifulSoup库来发送HTTP请求和解析HTML。 import requestsfrom bs4 import BeautifulSoup 发送GET请求获取登录页面:使用requests库发送GET请求&#…...
asp.net企业招聘管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio计算机毕业设计
一、源码特点 asp.net 企业招聘管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使用c#语 言开发 asp.net企业招聘管理系统 二、功…...
艾泊宇产品战略:假如中国禁止直播带货,网红和店家该如何应对?
近日,印尼宣布将禁止直播带货,这一消息引起了广泛关注。有人欢喜有人忧,很多人为此拍手叫好,但也有很多人为此感到担忧。 今天,我们就来做一个战略推演,假设中国也禁止直播带货,入局直播带货者…...
C#调用C/C++从零深入讲解
C#调用非托管DLL从零深入讲解 一、结构对齐 结构对齐是C#调用非托管DLL的必备知识。 在没有#pragma pack声明下结构体内存对齐的规则为: 第一个成员的偏移量为0,每个成员的首地址为自身大小的整数倍子结构体的第一个成员偏移量应当是子结构体最大成员的整数倍结构体总大小…...
MyBatis篇---第五篇
系列文章目录 文章目录 系列文章目录一、MyBatis 中见过什么设计模式?二、MyBatis 中比如 UserMapper.java 是接口,为什么没有实现类还能调用? 一、MyBatis 中见过什么设计模式? 二、MyBatis 中比如 UserMapper.java 是接口&#…...
十三水中各种牌型判断LUA版
近期回归程序行业,由于业务需求需要做十三水游戏,什么是十三水就不在多讲,下面是判断十三水牌型的方法(带大小王) GetSSSPaiType {}; local this GetSSSPaiType; local huaseTable {}; local numTable {}; functi…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
