Synchronized关键字

JavaScript 书签脚本实战:腾讯/优酷/爱奇艺等5大视频站m3u8链接一键提取 本文详细介绍了如何使用JavaScript书签脚本一键提取腾讯视频、优酷、爱奇艺等五大视频平台的m3u8流媒体链接。通过分析播放器内部对象结构,开发者可以高效获取视频源文件,避免录屏画质损失。文章包含各平台适配方案、实战增强功能开发及企业级解决方案设计,帮助用户快速掌握这一实用技术。 阅读详情

Synchronized关键字思维导图

1.Synchronized的作用

能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。

2.Synchronized的地位

1.Synchronized是Java的关键字,被Java语言原生支持

2.是最基本的互斥同步手段

3.是并发编程中的元老级角色,是并发编程的必学内容

3.Synchronized的两个用法

对象锁

包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)

方法锁形式:synchronized修饰普通方法,锁对象默认为this

代码块形式:手动指定锁对象

类锁

指synchronized修饰静态的方法或指定锁为Class对象

概念(重要):

只有一个Class对象:Java类可能有很多个对象,但只有一个Class对象

本质:所谓的类锁,不过是Class对象的锁而已

用法和效果:类锁只能在同一时刻被一个对象拥有。

形式一:synchronized加在static方法上

形式二:synchronized(*.class)代码块

4.不使用并发手段会有什么后果?如何解决?

解决问题:两个线程同时a++,最后结果会比预计的少

原因

count++,它看上去只是一个操作,实际上包含了三个动作:

1.读取count

2.将count加一

3.将count的值写入到内存中

这三个操作,如果不按照原子去执行,就会带来并发问题

解决办法:
对象锁:

1.方法锁形式:在普通方法上加上sychronized关键字:

@Override
public synchronized void run() {
    for (int j = 0; j < 100000; j++) {
        i++;
    }
}

2.同步代码块加锁:

@Override
public void run() {
    synchronized (this) { 
        for (int j = 0; j < 100000; j++) {
            i++;
        }
    }
}

类锁:

1.静态方法上加锁:

@Override
public void run() {
    count();
}
synchronized static void count() {
    for (int j = 0; j < 100000; j++) {
        i++;
    }
}

2.synchronized(*.class)代码块:


@Override
public void run() {
    synchronized (DisappearRequest1.class) {
        for (int j = 0; j < 100000; j++) {
            i++;
        }
    }
}

4.多线程访问同步方法的七种情况(面试常考)

1.两个线程同时访问一个对象的同步方法(对象锁)

这种情况就是对象锁的方法锁情况。会相互等待,只能有一个线程持有锁。

2.两个线程访问的是两个对象的同步方法

不会加锁,因为访问的是不同的实例

3.两个线程访问的是synchronized的静态方法

这种情况就是类锁的静态方法锁。

4.同时访问同步方法与非同步方法

synchronized关键字只作用于当前方法,不会影响其他未加关键字的方法的并发行为。因此非同步方法不受到影响,还是会并发执行。

5.访问同一个对象的不同的普通同步方法(对象锁)

synchronized关键字虽然没有指定所要的那个锁对象,但是本质上是指定了this这个对象作为它的锁。所以对于同一个实例来讲,两个方法拿到的是同一把锁,因此会出现串行的情况。

6.同时访问静态synchronized和非静态synchronized方法

前者为类锁,锁为Class类;后者为对象锁,锁为this对象。因此两者的锁不同,会并行执行。

7.方法抛异常后,会释放锁么?

Lock类加锁时,如果出现异常,不显式手动释放锁的话,Lock是不会释放的。

而synchronized不同,一旦出现异常,会自动释放锁。

也就是说当第二个线程等待一个被synchronized修饰的方法时,若第一个线程出现异常退出,这把锁会立刻释放并且被第二个线程所获取到。JVM会自动把锁释放。

8.扩展:线程进入到一个被synchronized修饰的方法,而在这个方法里面调用了另外一个没有被synchronized修饰的方法,这个时候还是线程安全的吗?

答案:不是的。出了本方法后,由于另外的方法没有被synchronized修饰,所以说这个方法可以被多个线程同时访问的。

5.七种情况总结:三点核心思想

1.一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应第1、5种情况);2.每个实例都对应有自己的一把锁,不同实例之间互不影响;
例外:锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象共用同一把类锁,这就是类锁的两种情况(对应第2、3、4、5种情况);3.无论方法是正常执行完毕或者抛出异常,都会释放锁(对应第7种情况)。

只需要对这三点核心思想理解透彻了,所有情况都是这三点核心思想的实例化的表现。

6.Synchronized的两个性质

1.可重入(synchronized区别于其他锁的一个很重要的性质)

什么是可重入:指的是同一线程的外层函数获得锁之后,内层函数可以直接再次获取该锁。也叫做递归锁。Java中两大递归锁:Synchronized和ReentrantLock

好比买车摇号,只要摇到一次号,可以给家里的第一辆车、第二辆车…所有车都上牌,直到我不需要上牌为止。这就叫做可重入性。如果每辆车上牌都需要摇一次号,这就叫做不可重入性。

锁的不可重入性:线程拿到一把锁了,如果想再次使用这把锁,必须先将锁释放,与其他线程再次进行竞争。
锁的可重入性:如果线程已经拿到了锁,试图去请求这个已经获得到的锁,而无需提前释放,直接就可以使用手里的这把锁,这就叫做可重入性

好处:避免死锁、提升封装性

1.假如有两个synchronized修饰的方法1和方法2,此时线程A执行到了方法1,并且获得了方法1的锁,此时方法1调用了方法2,由于方法2也是synchronized修饰的,假设synchronized不具备可重入性的话,那么线程A虽然拿到了方法1的锁,但是由于不可重入,它无法使用本身获得的方法1的这把锁。这样一来,它既想拿锁又不释放锁,这样就会永远等待,形成了死锁。所以由于synchronized具备可重入性,就避免了这种情况的发生。

2.避免了一次又一次的解锁加锁的过程,利用其可重入的性质提高了封装性,简化了并发编程的难度。

粒度:线程而非调用(用三种情况来说明和pthread的区别)
情况1:证明同一个方法是可重入的

情况2:证明可重入不要求是同一个方法

情况3:证明可重入不要求是同一个类中的

2.不可中断(相比于其他有的锁可以中断,这个性质是synchronized的一个劣势所在)
一旦这个锁已经被别的线程获得了,如果当前线程还想获得,只能选择等待或者阻塞,直到别的线程释放这个锁。如果别的线程 永远不释放锁,那么线程只能永远地等下去。

相比之下,Lock类,可以拥有中断的能力。

第一点,如果我觉得我等的时候太长了,有权中断现在已经获取到锁的线程的执行; 第二点,如果我觉得我等待的时间太长了不想再等了,也可以退出。

Lock比synchronized灵活很多,但是编码易出错。

7.深入原理

1.加锁和释放锁的原理:现象、时机、深入JVM看字节码
现象:
每一个类的实例对应一把锁,而每一个synchronized方法都必须先获得调用该方法的类的实例的锁方能执行,否则线程会阻塞。而方法一旦执行,它就独占了这把锁,直到该方法返回或者是抛出异常,才将锁释放。一旦锁释放之后,之前被阻塞的线程才能获得这把锁,从被阻塞的状态重新进入到可执行的状态。当一个对象中有synchronized修饰的方法或者代码块的时候,要想执行这段代码,就必须先获得这个对象锁,如果此对象的对象锁已经被其他调用者所占用,就必须等待它被释放。所有的Java对象都含有一个互斥锁,这个锁由JVM自动去获取和释放,我们只需要指定这个对象就行了,至于锁的释放和获取不需要我们操心。

获取和释放锁的时机:内置锁
我们知道每一个Java对象都可以用作一个同步的锁,这个锁叫做内部锁,或者叫做监视器锁–monitor lock。线程在进入到同步代码块之前,会自动获得这个锁,并且在退出同步代码块的时候会自动的释放这个锁,无论是正常途径退出还是抛出异常退出。获得这个内置锁的唯一途径就是进入这个锁保护的同步代码块或者同步方法中。这样一来就理解了时机。

等价代码:
Lock lock = new ReentrantLock();public synchronized void method1 () {
System.out.println(“我是synchronized形式的锁”);
}public void method2() { lock.lock(); try {
System.out.println(“我是lock形式的锁”);
} finally { lock.unlock();
}
}

第一个方法和第二个方法等价,相当于把synchronized拆分成lock在进入方法的时候回隐形的获取一把锁,等价于第二个方法的lock.lock();代码所做的事情
而在退出或者抛出异常的时候会释放锁,等价于lock.unlock();代码所做的事情

深入JVM看字节码:反编译、monitor指令

1.编写一个类:

package demo;/**
 * @Description: 反编译字节码
 * @Author: jiangfan
 * @CreateTime 2019/1/14 上午10:22
 */public class Decompliation14 {    private Object object = new Object();    public void insert(Thread thread) {        synchronized (object) {

        }
    }
}
2.javac编译该类:

javac Decompliation14.java
3.反编译后:

javap -verbose Decompliation14.class


线程既可以在方法完成之后退出,也可以在抛出异常后退出,因此monitorexit数量多于monitorenter。

monitorenter和monitorexit指令
monitorenter:线程每次进入时,计数器+1。如果重入,继续加

monitorexit:线程退出时,计数器-1.变为0时候,其他线程可以获取锁。

可重入原理:加锁次数计数器

1.每个对象都有一把锁,JVM负责跟踪对象被加锁的次数。

2.线程第一次给对象加锁的时候,计数变为1。每当这个相同的线程再次对象上再次获得锁时,计数会递增。只有首先获得这个锁的线程才能继续的在这个对象上多次的获取这把锁。

3.每当任务离开时,计数递减,当计数为0的时候,锁被完全释放。

保证可见性的原理:Java内存模型
线程A向线程B发送数据的两个步骤:

1.线程A修改了本地内存A,并将其存储到主内存中。

2.线程B再从主内存中读取出来。

这个过程是由JMM(Java Memory Model)控制的。JMM通过控制主内存与每个线程的本地内存的交互来为Java程序员提供内存可见性的保证。

synchronized是如何做到内存可见性的实现?
一旦一个代码块或者方法被synchronized修饰之后,那么它在执行完毕之后被锁住的对象所做的任何修改都要在释放锁之前从线程内存写回到主内存中。所以下一个线程从主内存中读取到的数据一定是最新的。就是通过这样的原理,synchronized关键字保证了每一次执行都是可靠的,保证了可见性。

8.Synchronized的缺陷

1.效率低:

锁的释放情况少

试图获得锁时不能设定超时

不能中断一个正在试图获得锁的线程

2.不够灵活(读写锁更灵活:读操作的时候不会加锁,写操作的时候才会加锁):

加锁和释放的时机单一

每个锁仅有单一的条件(某个对象),可能是不够的

3.无法知道是否成功获取到锁

Lock可以,如果尝试成功了做一些逻辑判断,如果没有成功做另外一些逻辑判断.

Lock类:
lock.lock();lock.unlock();
通过这两个方法,可以手动加锁和解锁。

lock.tryLock();lock.tryLock(10, TimeUnit.MINUTES);
可以判断是否加锁,返回类型为boolean

9.常见面试问题

1.synchronized的使用注意点:

锁对象不能为空:锁的信息保存在对象头里面 作用域不宜过大:synchronized关键字包裹的范围。不需要串行工作的情况下,用并行的方式可以提高运行的效率 避免死锁

2.如何选择Lock和synchronized关键字?

1.如果可以的情况下,两者都不要选择,而是使用java.util.concurrent包中的各种各样的类,例如:CountDownLatch等。使用这些类,不需要自己做同步工作,更方便,也更不容易出错。

2.如果synchronized关键字在程序中适用,就优先实用这个关键字。因为这样可以减少需要编写的代码,就减少了出错的几率。

3.如果特别需要Lock这样结构独有的特性的时候,才使用Lock。

以上三点主要是基于减少代码出错为出发点。

3.多线程访问同步方法的各种具体情况

看4.多线程访问同步方法的七种情况

10.思考题

1.多个线程等待同一个synchronized锁的时候,JVM如何选择下一个获取锁的是哪个线程?
锁调度机制。对于synchronized内置锁,不同版本的JVM处理方式不同,blocked和running都有几率

2.synchronized使得同时只有一个线程可以执行,性能较差,有什么办法可以提升性能?
优化使用范围,让加锁区在业务允许的情况下足够小。

用其他类型的锁,例如读写锁,这样在读的时候就不止一个线程可以同时进入代码。

3.我想更灵活地控制锁的获取和释放(现在释放锁的时机都被规定死了),怎么办?
自己实现一个Lock

4.什么是锁的升级、降级?什么是JVM里的偏斜锁、轻量级锁、重量级锁?
在之前的JVM版本中,synchronized性能不是特别的好,而经过不断的迭代,synchronized性能已经得到了显著的提高,这里面运用的技术就是偏斜锁、轻量级锁、重量级锁。JVM会根据synchronized关键字使用到的次数或者其他的种种指标对锁进行有效的优化使得性能得到大幅上涨,这里面还涉及到了对象头里面的字段。

11.总结

一句话介绍synchronized:

JVM会自动通过使用monitor来加锁和解锁,保证了同时只有一个线程可以执行指定代码,从而保证了线程安全,同时具有可重入性和不可中断的性质。

FPGA原型验证(八):SoC设计适配与实现策略 时钟门控在SoC设计中很常见,应该小心处理门控时钟,以成功地在FPGA上原型化SoC设计。现代FPGA综合工具在正确约束的情况下,可以自动处理大多数门控时钟。通过遵循本章中的指导方针,即使具有复杂时钟门控的SoC设计也可以得到处理,并成功地在FPGA上进行原型化。 阅读详情

相关推荐

跟着Synopsys报告,一步步拆解车规芯片FMEDA计算(含公式与避坑点)

本文详细解析了车规芯片FMEDA计算的全流程,基于Synopsys报告拆解实战指南,涵盖基础失效率建模、安全机制效能评估及安全指标合成等关键步骤。通过公式解析、数据准备清单和避坑点分享,帮助工程师掌握ISO26262标准下的硬件量化分析技术,提升车载系统设计可靠性。

weixin_30460489的博客 195

Synchronized锁

Synchronized锁原理及锁的升级过程

T_karine的博客 3710

4.7W防削顶单声道D类音频功率放大器HT6872介绍

HT6872是一款低EMI,防削顶失真,单声道免滤波D类音频功率放大器。在6.5V电源,10%THD+N,4Ω负载条件下,输出4.71W功率,在各类音频终端应用中维持高效率并提供AB类放大器的性能。

weichen_78的博客 4700

10-锁(synchronized和Lock)

锁(synchronized和lock)

titanium的博客 3968

解决Unity与3DMax模型单位与中心点偏差的完整指南

本文详细解析了Unity与3DMax模型导入时常见的单位与中心点偏差问题,提供了从3DMax单位设置、FBX导出到Unity接收调整的完整解决方案。通过实战案例和高效工作流建议,帮助开发者实现unity与3dmax的单位统一,避免尺寸错误和轴心偏移,提升3D资源导入效率。

weixin_29015899的博客 286

深度学习助力台风路径预测:技术剖析与实战应用全攻略(基于LSTM模型)

摘要:深度学习技术在台风路径预测领域展现出巨大潜力。通过融合多源气象数据,深度学习模型如LSTM能有效处理时间序列数据,捕捉台风路径变化规律。与传统方法相比,深度学习模型在自动特征学习和处理复杂模式方面具有独特优势,提高了预测的准确性和实时性。然而,挑战依然存在,包括数据质量问题、模型可解释性不足以及极端台风的复杂性。未来,随着观测技术的进步和新算法的开发,深度学习将在台风路径预测中发挥更大作用,为防灾减灾提供更精准的决策支持。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2229

方法上的 synchronized

两种情况: 第一种情况:synchronized加在普通方法上 class Test{ public synchronized void test() { } } //等价于 class Test{ public void test() { synchronized(this) { }

weixin_42383680的博客 4340

Dify 第 13 篇 Dify 工作流 详解

工作流通过将复杂任务分解为节点降低复杂度,提升LLM应用的性能和稳定性。Dify工作流分为两类:Chatflow面向对话场景(如客服),支持多轮对话;Workflow面向批处理场景(如翻译),提供逻辑节点实现自动化。核心概念包括节点、变量(系统/会话/环境变量)及应用类型差异:Chatflow支持中间输出和对话历史,Workflow仅支持结束节点输出。系统变量以"sys"开头,用于全局数据传递,不同应用类型变量不同,如Chatflow的sys.query存储用户输入,Workflow的s

甘蓝的专栏 3249

我去,你竟然还不会用 synchronized

我去,你竟然还不会用 synchronized

qq_41490913的博客 177

手把手教你学Simulink--双足机器人的反步控制方法仿真

本文介绍了在Simulink中基于反步控制方法进行双足机器人仿真研究的步骤。主要内容包括:1)准备工作,包括MATLAB/Simulink安装和相关工具箱配置;2)构建简化双足机器人模型;3)设计反步控制器,阐述其递归设计原理及Lyapunov函数构造方法;4)通过MATLAB Function块实现控制逻辑并连接模型;5)仿真参数配置和结果分析。文章强调反步控制适用于非线性系统,通过逐步构造虚拟控制律保证系统稳定性,并指出需要多次调试和查阅文献来优化控制效果。该教程为研究双足机器人运动控制提供了实用的仿真

MHD0815的博客 153

超十万字解读Spring AI实战:开篇

大模型技术正以惊人的速度改变世界,2025年的人工智能已不再是科幻,而是现实。大模型如ChatGPT等,正在重塑各行各业,降低技术门槛,使专业能力普及化。SpringAI的出现为Java开发者提供了桥梁,使其能在企业级系统中稳定运行AI,同时保持工程化思维。尽管SpringAI在生态、学习成本和性能上存在不足,但其企业级基因和国产化适配能力使其成为Java开发者的重要工具。本系列文章旨在介绍SpringAI的功能与特性,鼓励更多Java开发者参与AI实践,共同探索AI时代的无限可能。

liaokailin的专栏 1578

synchronized用法详解

synchronized 是 Java 中的关键字,是一种同步锁。主要应用于多线程环境下保证线程的安全性。A. 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。B. 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。C. 实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

qq_43842093的博客 7681

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

synchronized关键字

synchronized关键字

我从不打没有准备的仗! 9852

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Synchronized 关键字原理

众所周知synchronized关键字是解决并发问题常用解决方案,有以下四种使用方式: 修饰代码块,即同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象。 修饰方法,即同步方法,其作用的范围是整个方法,作用的对象是调...

钱立清的博客 6万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

synchronized 关键字详解

synchronized 关键字1. synchronized 关键字的三种使用方法1.1. 修饰实例方法2.2. 修饰静态方法3.3. 修饰代码块2. 双重检验锁方式实现单例模式3. 构造方法可以使用 synchronized 关键字修饰么?4. JDK1.6 之后的 synchronized 关键字底层做了哪些优化?5. synchronized 和 ReentrantLock 的区别6. synchronized 关键字与Lock的区别 synchronized 关键字解决的是多个线程之间访问资源的同

TanaStudy的博客 7388

synchronized 关键字

synchronized 是 Java 的一个关键字,用于实现多个线程之间资源访问的同步性,可以保证被它修斯的方法或者代码块在任意时刻都只有一个线程执行。

好记性不如烂笔头 971

synchronized 关键字的底层原理

synchronized关键字实现了多个线程之间访问资源的同步性,保证了被它修饰的方法或代码块在任意时刻最多只有一个线程执行。 synchronized关键字是通过JVM底层实现的。 按使用位置分,同步语句块和同步方法实现线程安全的方式不同 synchronized关键字同步语句块 public class SynchronizedDemo { public void method() ...

Rosen's 615

synchronized 关键字底层原理

synchronized 关键字底层原理属于 JVM 层面。 ① synchronized 修饰同步语句块 public class SynchronizedDemo { public void method() { synchronized (this) { System.out.println("s...

happyJared 441

java synchronized关键字_Java synchronized 关键字,你用的对吗?

for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread.getName + " " + i);}System.out.println("Completed printing Numbers for " + Thread.currentThread.getName);}代码中只是给方法添加了一个synchroni...

weixin_42397141的博客 109

synchronized关键字详解

Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。也就是说,仅仅是发生在STW的时候,只有垃圾回收线程能够观测到它,在我们正常使用的过程中是不会发生锁降级的,只有在GC的时候才会降级。修饰的代码,在开始执行时会加锁,执行完成后会进行解锁。所以,在JDK1.6中出现对锁进行了很多的优化,进而出现轻量级锁,偏向锁,锁消除,适应性自旋锁,锁粗化。

努力分享一些干货 1035
上一篇: 程序编译及代码优化
下一篇: CommonsMultipartFile转File
coder_flag
博客等级 码龄9年 2粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值