java高并发、多线程(三)--synchronized

JAVA的多线程与高并发 概念 进程 进程指正在运行的程序,进程拥有一个完整的、私有的基本运行资源集合。通常,每个进程都有自己的内存空间。 进程往往被看作是程序或应用的代名词,然而,用户看到的一个单独的应用程序实际上可能是一组相互 协作的进程集合。 为了便于进程之间的通信,大多数操作系统都支持进程间通信(IPC),如pipes 和sockets。IPC不仅支持同一系统上的通信,也支持不同的系统。IPC通信方式包括管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等方式,其中 Socket 阅读详情

synchronized

先看下面例子:

public class SynchronizedTest {
    static int count = 0;
    public static void add() {
        for (int i = 0; i < 10000; i++) {
            count++;
        }
    }

    public static void main(String[] args) {
        List<Thread> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(new Thread(SynchronizedTest::add,"Thread-"+i));
        }
        list.forEach(t->t.start());
        list.forEach(t-> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(count);
    }
}

运行结果:
在这里插入图片描述
以上代码开启10个线程对count进行累加10000次,我们希望的结果是10万,但是最终结果是小于等于10万的。这是由于count++这个操作并不是原子操作,代码产生了同步问题,我们可以给相关代码加上锁来解决上面的问题。

加锁的方式

  • 同步代码块上加锁
	private static Object object = new Object();
    public static void add() {
        for (int i = 0; i < 10000; i++) {
            synchronized (object){
                count++;
            }
        }
    }
  • 方法上加锁
    public synchronized static void add() {
        for (int i = 0; i < 10000; i++) {
                count++;
        }
    }

运行结果:
在这里插入图片描述

synchronized的性质

  • 保证线程间可见性
	static int count = 0;

我们可以观察到上述代码中,我们并没有给count变量采用volatile修饰,但是程序的运行结果是正确的,那么说明synchronized可以替代volatile,能够保证线程间的可见性。

那volatile可以替代synchronized吗?
我们对上述代码做如下修改:

	volatile static int count = 0;
    public /*synchronized*/ static void add() {
        for (int i = 0; i < 10000; i++) {
                count++;
        }
    }

运行结果:
在这里插入图片描述
由运行结果可知:volatile并不能替代synchronized的作用,它不能保证多个线程共同修改共享变量所带来的不一致问题。

  • synchronized获得的是重入锁
    修改上述代码:
	static int count = 0;
    public synchronized static void add() {
        for (int i = 0; i < 10000; i++) {
                count++;
        }
        //调用另一个同步方法
        sub();
    }
    public synchronized static void sub() {
        for (int i = 0; i < 10000; i++) {
            count--;
        }
    }

运行结果:
在这里插入图片描述
从运行结果可以知道,一个同步方法可以调用另一个同步方法。

synchronized锁升级

偏向锁
自旋锁
重量级锁

优化

  • 采用细粒度的锁,减少同步代码块中代码量

注意事项

  • 不使用字符串作为锁对象
    例如:
public class SynchronizedTest {

    String lock1 = "lock";
    String lock2 = "lock";

    public void m1(){
        synchronized (lock1){
            System.out.println("m1 start");
            while(true){}
        }
    }
    public void m2(){
        synchronized (lock2){
            System.out.println("m2 start");
            while(true){}
        }
    }

    public static void main(String[] args) {
        SynchronizedTest st = new SynchronizedTest();
        new Thread(st::m1).start();
        new Thread(st::m2).start();
    }
}

运行结果:
在这里插入图片描述
由上面的例子可以看出:代码原意是想m1与m2方法获取不同的锁,但是由于string常量池的性质,导致两把锁实际上指向的是同一个对象,从而m1与m2方法仅能执行其中的一个。

  • 不要改变锁的引用
    例如:
public class SynchronizedTest {

    private Object o = new Object();

    public void m1(){
        synchronized (o){
            System.out.println("m1 start");
            while(true){}
        }
    }
    public void m2(){
        synchronized (o){
            System.out.println("m2 start");
            while(true){}
        }
    }

    public static void main(String[] args) {
        SynchronizedTest st = new SynchronizedTest();
        new Thread(st::m1).start();
        try {
            Thread.sleep(1000);
            //改变o指向的对象
            st.o = new Object();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(st::m2).start();
    }
}

运行结果:
在这里插入图片描述
从这个例子可以看出,当改变了锁对象的引用后m2方法可以得到执行。因此锁对象建议加上final关键字修饰

	private final Object o = new Object();
【Java面试并发多线程】Synchronized锁的讲解 在我们和面试官吹多线程的时候,我们务必会涉及到锁的问题,这就需要我们死磕并发并深入剖析synchronized底层原理了,希望可以帮到你,哈哈~~ 1.面试经验: 面试官问你,你有没有接触过多线程的问题 复习的不错的朋友可以说:有接触到,在项目中因为一些业务,哪哪有使过多线程,怎么使用的,然后再去深入讲解多线程知识。 如果你之前只是粗略的学习过多线程,面试初级开发的话,你可以这样回答:因为项目的限制,很少使用多线程,但是多线程怎么使用还是会的,也做过一些窗口卖票的多线程小案例。 2.线程的并发问题: 在 阅读详情

相关推荐

Java多线程——synchronized,volatile,CAS,ReentrantLock

当没有线程占用锁对象时处于无锁,当有一个线程占用该锁时变成偏向锁,偏向搜不是真的加锁,而是添加一种锁标记,如果之后没有发生锁竞争就无须开销锁资源,如果有锁竞争就添加自旋锁,自旋锁是一种轻量级锁,在锁冲突不激烈的情况下,在抢占不到锁时不会处于阻塞状态而会一致尝试抢占锁,当锁竞争激烈时,自旋锁不能马上获取到锁,就会膨胀为重量级锁,调用OS的mutex将没有抢占到锁的线程加入到阻塞队列中,重量级锁的具体执行过程如上述介绍。.lock前缀指令在多核处理器中会做2件事情:将当前工作内存中的变量的值写回到主内存中;

weixin_52477733的博客 718

Java synchronized代码块锁字符串无效的问题解决方案

Java synchronized代码块锁字符串无效的问题解决方案 //test测试方法,直接锁住字符串,是没有效果的,因为synchronized(str)相当于重新new String(str)一个字符串作为锁住的参数,每个对象的hashcode不同,所以没有效果。 public static void test(String str) { synchronized(str) { System.out.println("进来啦" + str); try { Thread.sl

lluohuih的专栏 1664

【Java多线程】内置锁(Synchronized)的前世今生

**Java内置锁不需要显式的获取锁和释放锁,由JVM内部来实现锁的获取与释放。而且任何一个对象都能作为一把内置锁。在`JDK1.4`及之前就是使用`内置锁Synchronized`来进行线程同步控制的** `上文说,任何一个对象都能作为一把内置锁”,意味着synchronized关键字出现的地方,都有一个对象与之关联`,具体表现为: - 当synchronized作用于`普通方法`时,锁对象是`this`; - 当synchronized作用于`静态方法`时,锁对象是`当前类的Class对象`; -

墩墩分墩 3764

如何通过Java中的对象值来同步块

问题 有时,我们需要通过变量的值来同步代码块。 为了解这个问题,我们将考虑一个简单的银行应用程序,它对客户的每次转账进行以下操作: 通过此外部Web服务转移评估现金返还金额(CashBackService) 在数据库中执行汇款(AccountService) 更新现金返还评估系统中的数据(CashBackService) 汇款操作如下: public void withdrawM...

Tybyqi的博客 1033

软件工程实验报告--用Visio绘制数据流图、ER图、状态图、软件结构图、程序流程图、系统流程图

用Visio绘制数据流图、ER图、状态图、软件结构图、程序流程图、系统流程图

m0_73814332的博客 4162

嵌入式STM32控制电梯面板

嵌入式STM32控制电梯面板 用点阵来显示电梯向上还是向下运动,用数码管来显示楼层数(由于灯阵显示楼层数比较困难故用数码管代替)。当按下对应的按钮,就可以去到对应层数,可上升可下降。 #include "stm32f10x.h" #include "stm32f10x_exti.h" #include "stm32f10x_it.h" #define uint unsigned int #define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_10) #define

code_init_的博客 2111

java并发基础-Synchronized

基础使用 基本上Java程序员都简单的了解synchronized的使用: 无非就是用在多线程环境下的同步。 看如下简单的例子: publicclassUnsafeCounter{ privateint count=0; publicint getAndIncrement(){ returnthis.count++; } }    上面是一个简单的非常常见的...

216

WSL基础环境配置方案

通过以上步骤,您已经在 Windows 的 WSL 环境中成功搭建了一个完整的基础开发环境,包含 Docker、Kubernetes、Helm、kubectl、yq、Git 等工具。这套环境特别适用于在国内使用阿里云镜像服务部署和管理 Tekton,提升了开发和运维的效率和稳定性。

落魄书生的职业学习生涯 8876

【Java】多线程和高并发编程(三):锁(上)锁的分类、深入synchronized

偏向锁在升级为轻量级锁时,会涉及到偏向锁撤销,需要等到一个安全点(STW),才可以做偏向锁撤销,在明知道有并发情况,就可以选择不开启偏向锁,或者是设置偏向锁延迟开启。:如果在一个循环中,频繁的获取和释放做资源,这样带来的消耗很大,锁膨胀就是将锁的范围扩大,避免频繁的竞争和获取锁资源带来不必要的消耗。:当前线程获取到A锁,在获取之后尝试再次获取A锁,无法获取到的,因为A锁被当前线程占用着,需要等待自己释放锁再获取锁。:线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,先尝试竞争一波。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

MOOS-ivp实战:从零搭建水下机器人通信系统(Ubuntu 22.04版)

本文详细介绍了在Ubuntu 22.04系统上从零开始搭建MOOS-ivp水下机器人通信系统的完整实战流程。内容涵盖环境准备、核心安装、MOOSDB通信模型解析、自定义应用节点开发、以及调试监控工具链的使用,旨在帮助开发者快速掌握这一分布式机器人系统框架,构建稳定可靠的水下机器人通信与控制系统。

snow3的博客 636

TM1650数码管驱动芯片

简介 TM1650是一款国产4位共阴数码管驱动芯片,它还带有矩阵按键扫码功能。它的基本参数如下: 工作电压:3~5V 数码管驱动模式:8段x4位共阴数码管 矩阵按键驱动模式:7x4矩阵按键,不支持组合键 通信接口:类IIC,使用了IIC相同的时序,但没有完全遵守IIC的协议,不带从机地址 引脚定义 SCL:串行通信时钟线 SDA:串行通信数据线 做数码管驱动使用时 DIGx:数码管的位选引脚,灌电流驱动,最大可吸收150mA电流 A~DP:数码管的段驱动引脚,拉电流驱动,最大可输出25m

luliplus的博客 4万+

java多线程和高并发系列三 & Synchronized锁详解

java多线程和高并发系列三 & Synchronized锁详解 偏向锁 轻量级锁 自旋锁 重量级锁

weixin_37552984的博客 662

RT-DETR改进策略【独家融合改进】| SPD-Conv+PPA 再次提升模型针对小目标的特征提取能力

SPD-Conv是一种新的 CNN 构建模块,用于替代传统 CNN 架构中使用的步长卷积(strided convolution)和池化(pooling)层,它由空间到深度(Space-to-depth,SPD)层和非步长卷积(non - strided convolution)层组成。

Limiiiing的博客 1154

多线程与高并发

进程是操作系统进行资源分配的基本单位Java 内存模型规定所有的共享变量都是存在主存当中(类似于前面说的物理内存),每个线程都有自己的工作内存(比如CPU的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作,并且每个线程不能访问其他线程的工作内存。之所以要用自己的本地内存,主要是利用缓存和改变执行代码顺序达到程序执行效率优化。

2304_80073016的博客 633

高通 vs MTK vs 海思:三大平台 ISP 架构横向对比与实战差异分析

随着移动影像能力成为智能终端差异化竞争的核心维度,ISP(Image Signal Processor)架构日益重要。高通、MTK、海思三大 SoC 厂商在 ISP 设计上各具特色,不仅在图像处理链路、模块集成度、算法加速路径等方面存在显著差异,同时也决定了终端厂商在成像质量、调试复杂度与扩展能力上的实际表现。本文将基于真实平台项目经验,横向对比三大主流平台的 ISP 架构关键指标,系统分析其在实际开发过程中的能力边界、工程成本与调优空间,帮助工程师更精准地进行平台选型与优化策略制定。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3932

芯片工程师-必须掌握的linux操作-第一讲

一个从材料专业,转行芯片验证初级工程师,自己也是从0基础开始学习入门,更知道0基础的人应该怎么去学习。 现在工作三个多月了,特地花时间给大家写这篇文章。希望能关注、支持下。 为什么芯片验证工程师必须要学习linux命令? 答: ① 芯片工程师主要的职责,就是与IC设计工程师和系统工程师密切合作,开发验证平台,能够根据项目要求产生测试计划,产生代码及功能覆盖率,撰写验证报告。 ②简单点说,主要工作内容,是编写代码去验证设计的对不对。 那么问题来了,编写代码,在什么环境呢,我现在告诉你,都是在linux系统中进

小白蒋-材料转行芯片验证 4841

Java多线程与高并发

当谈到计算机数据存储和传输时,我们使用位(bit)和字节(byte)来表示不同的数据量。一个位代表一个二进制数字,可以是0或1。而一个字节由8个位组成,可以表示256种不同的状态。字节是计算机中最常用的存储单位,用于表示字符、整数、图像等各种数据类型。在Java开发中,字节和位的关系非常重要。Java中的基本数据类型(如int、char)都占用特定数量的字节,以对应不同范围的数值。例如,int类型占用4个字节,可以表示范围更大的整数值。理解字节和位的关系对于编写高效的程序至关重要。

1468

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【Java 多线程】Synchronized

偏向锁状态下,线程要获取锁时,会在 MarkWord 中直接记录线程 ID,只要线程来执行代码了,会对比线程 ID 是否相等,相等直接获取锁,执行同步代码,不相等则尝试使用 CAS 修改 MarkWord 中的线程 ID ,如果修改成功则获取锁,修改不成功说明有竞争,因此会撤销偏向锁升级为轻量级锁。在内存中,对象一般由三部分组成,分别是对象头、实际数据和对齐填充,重点在与对象头,对象头中有一个我们比较关注的部分,MarkWord,MarkWord 中记录了有关锁的信息包括锁标记位,是否为偏向锁等。

栗子的博客 2252

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Java多线程——synchronized关键字

虽然说synchronized已经优化了很多,但是了lock 还是存在一定差距的在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所有的Java对象是天生的Monitor,每一个Java对象都有成为Monitor的潜质,因为在Java的设计中,每一个Java对象自打娘胎里出来就带了一把看不见的锁,它叫做内部锁或者Monitor锁。

jcc4261的博客 1007

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

java多线程之synchronized详解

通过4问题,我们可以看到,通常情况下,为了保证多线程间的有效并发, 会要求每个线程持有锁的时间尽可能短,但是大某些情况下,一个程序对同一个锁不间断、高频地请求、同步与释放, 会消耗掉一定的系统资源,因为锁的讲求、同步与释放本身会带来性能损耗, 这样高频的锁请求就反而不利于系统性能的优化了,虽然单次同步操作的时间可能很短。每个对象都有一个监视器。当锁处于偏向锁状态后,这时出现了一个搅局者,被另外的线程访问了,这时偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,但是不会阻塞,从而提高了性能。

qq_43022896的博客 1305

java多线程(三)Synchronized

一、Synchronized 使用 多线程的情况下对共享变量的访问必须进行同步处理,否则会出现意想不到的结果。Synchronized关键字就是进行多线程同步用的。 Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。从语法上讲,Synchronized总共有三种用法:   (1)修饰普通方法

BNMB888的博客 429

多线程与高并发(2)——synchronized用法详解

这篇文章主要总结synchronized的用法,考虑到篇幅和方便自己记忆,synchronized的原理会在下篇文章详细总结。 一、定义 Synchronized是Java中常用的一个关键字。 Synchronized的作用主要有三个: (1)确保线程互斥的访问同步代码。——原子性 (2)保证共享变量的修改能够及时可见。——可见性 (3)有效解决重排序问题。——有序性 二、基础理论 这里只总结几大特性的基础理论,会在后续文章中陆陆续续结合关键字或者实例来讲解下面的特性。 1、共享性 在多线程编程中,数据共享

liwangcuihua的博客 1398

多线程与高并发系列二(Synchronized和volatile)

多线程与高并发系列二(Synchronized) synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有⼀个线程执行。

一只小菜鸡的博客 800

Java多线程与高并发专题——深入synchronized

Java多线程与高并发专题——深入synchronized

从知识输入到知识输出 994
上一篇: java高并发、多线程(二)--volatile
下一篇: java高并发、多线程(四)--AtomicInteger
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值