JAVA多线程并发(二)-- volatile和synchronized 详解

在Java并发编程中,volatile和synchronized是两个至关重要的关键字,它们帮助开发者解决多线程环境下的可见性、原子性和有序性问题。

一. 简介

1. Volatile

volatile是一个类型修饰符,用来确保对一个变量的读取和写入操作不会被编译器重排序,并且每次读取都直接从主内存中获取最新值,写入时也直接写入主内存,从而保证了多线程环境下的可见性。但需要注意的是,volatile不能保证复合操作(如count++)的原子性

volatile关键字用于确保变量的可见性(visibility)和有序性(ordering),但不保证原子性(atomicity)。

2. Synchronized

synchronized关键字可以用于方法或代码块,它提供了一种锁机制,确保同一时间只有一个线程可以执行特定的代码段,从而达到线程互斥的效果。synchronized不仅保证了可见性,还确保了操作的原子性以及有序性,是更强大的并发控制工具。

二、用法

1. Volatile 的使用

public class VolatileExample {private volatile int count = 0;public void increment() {count++;}public int getCount() {return count;}
}

在这个例子中,虽然count使用了volatile,但increment()方法并不是线程安全的,因为count++不是原子操作。然而,getCount()能保证读取到最新的count值。

2 Synchronized 的使用

  1. 方法级别
public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}
  1. 代码块级别
public class SynchronizedBlockExample {private int count = 0;private Object lock = new Object();public void increment() {synchronized (lock) {count++;}}public int getCount() {synchronized (lock) {return count;}}
}

三、常用案例实例

  1. Volatile 示例:确保一个标志的可见性
public class VolatileExample {  // 使用volatile关键字确保变量的可见性  private volatile boolean running = true;  public void start() {  new Thread(() -> {  while (running) {  // 模拟一些工作  System.out.println("Thread is running...");  try {  Thread.sleep(1000);  } catch (InterruptedException e) {  e.printStackTrace();  }  }  System.out.println("Thread is stopping...");  }).start();  }  public void stop() {  running = false; // 当running被设置为false时,其他线程会立即看到这个改变  }  public static void main(String[] args) {  VolatileExample example = new VolatileExample();  example.start();  // 模拟一段时间后停止线程  try {  Thread.sleep(5000);  } catch (InterruptedException e) {  e.printStackTrace();  }  example.stop(); // 设置running为false,期望线程停止  }  
}
  1. Synchronized 解决并发修改问题

考虑一个经典的银行账户转账问题:

public class BankAccount {private double balance;public synchronized void deposit(double amount) {balance += amount;}public synchronized void withdraw(double amount) {if (amount <= balance) {balance -= amount;} else {System.out.println("Insufficient balance.");}}public synchronized double getBalance() {return balance;}
}

在这个例子中,通过synchronized关键字确保了存取款操作的原子性和一致性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/837946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle多条重复数据,取最新的

1、原理讲解-可直接看2 筛选出最新的 SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (PARTITION BY LOCALAUTHID ORDER BY LASTUPDATETIME DESC) AS rn FROM USER_LOCALAUTH_STATE t ) t WHERE t.rn 1; 解释&#xff1a; 这个序号是基于[LOCALAUTHID]字段进行分…

外网ip地址怎么获取?快解析

大家都清楚互联网是通过ip地址通信的&#xff0c;ip地址又分内网ip和外网ip。内网ip只能在内网使用&#xff1b;而外网ip作为电脑唯一标识&#xff0c;可在公网使用。那么外网ip地址怎么获取呢&#xff1f; 外网ip是网络运营商分配给用户的。目前最常见的两种上网方式一个是拉…

图文详解JUC:Wait与Sleep的区别与细节

目录 一.Wait() 二.Sleep() 三.总结Wait()与Sleep()的区别 一.Wait() 在Java中&#xff0c;wait() 方法是 Object类中的一个方法&#xff0c;用于线程间的协作。当一个线程调用wait() 方法时&#xff0c;它会释放对象的锁并进入等待状态&#xff0c;直到其他线程调用相同对…

JVM调优-调优原则和原理分析

1.写在前面 对于JVM调优这个话题&#xff0c;可能大部分程序员都听过这个名词。 但是绝大多数程序员&#xff0c;都没有真真实实去干过&#xff0c;都没有真实的实践过。也不懂得如何调优&#xff1f;不知道要调成怎么样&#xff1f; 那今天咋们就对这个话题来展开描述一下&…

洛谷 P3372:线段树 1 ← 分块算法模板(区间更新、区间查询)

【题目来源】https://www.luogu.com.cn/problem/P3372【题目描述】 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; &#xff08;1&#xff09;将某区间每一个数加上 k。 &#xff08;2&#xff09;求出某区间每一个数的和。【输入格式】 第一行…

二叉树——初解

二叉树 树树的概念树的性质 二叉树二叉树的概念二叉树的性质二叉树的实现方式数组构建左孩子右兄弟法构建指针构建 树 树的概念 在计算机科学中&#xff0c;树&#xff08;Tree&#xff09;是一种重要的非线性数据结构&#xff0c;它由若干节点&#xff08;Node&#xff09;组…

Java面经学习2

来源 https://www.nowcoder.com/discuss/619573767051800576 1.一面内容 RocketMQ延时消息&#xff08;项目用到了&#xff09;底层怎么实现的&#xff08;不会&#xff09; 消息量太大导致读消息延迟时间很长怎么办 redis为什么快&#xff08;说了内存、数据结构优化、单线…

Chromium 调试指南2024 Windows11篇-调试变量监视(十)

1. 前言 设置断点和监视变量是调试过程中常用的两种技术手段。通过设置断点&#xff0c;我们可以暂停程序的执行并检查程序的内部状态&#xff0c;而监视变量则可以帮助我们实时查看程序中关键变量的值。本文将介绍如何在Chromium项目中进行断点设置和变量监视&#xff0c;帮助…

java内容快速回顾+SSM+SpringBoot简要概述

文章目录 java基础知识基本知识列表面对对象堆与栈的关系值修改与引用修改异常&#xff1a;错误异常 SSMspringMVCServletSpringMVC&#xff1a;基于 Servlet的 Spring Web 框架&#xff0c; spring控制反转 IoC(Inversion of Control)面向切面 Aop MybatisJDBCMybatis SpringB…

Git 基础使用(1) 入门指令

文章目录 Git 作用Git 安装Git 使用Git 仓库配置Git 工作原理Git 修改添加Git 查看日志Git 修改查询Git 版本回退 概念补充 Git 作用 Git 是一种分布式版本控制系统&#xff0c;它旨在追踪文件和文件夹的更改&#xff0c;并协助多人协作开发项目。 Git 安装 &#xff08;Lin…

Go 处理错误异常

在Go语言中错误和异常是两个完全不同的概念&#xff0c;错误指的是可能出现问题的地方出现了问题&#xff0c;而异常指的是不该出现问题的地方出现了问题 从Go语言的机制上讲错误和异常就是error 和panic的区别 错误&#xff08;Error&#xff09;&#xff1a;程序中预期会发生…

17.多线程

多线程 程序、进程、线程的概念 程序&#xff1a;是指令和数据的有序集合&#xff0c;是一个静态的概念。比如&#xff0c;在电脑中&#xff0c;打开某个软件&#xff0c;就是启动程序。 进程&#xff1a;是执行程序的一次执行过程&#xff0c;是一个动态的概念&#xff0c;…

c# 实现每个整数分钟执行一次的定时任务

StartAsync 方法中&#xff0c;计算了下一个整数分钟的时间&#xff0c;然后使用 System.Threading.Timer 类创建定时器&#xff0c;并将首次触发时间设为该时间。在 InsertDB2Async 方法中&#xff0c;我们定义了要执行的操作&#xff0c;然后使用 await Task.Delay(1000) 模拟…

mongo副本集本地部署

介绍 前言&#xff1a; mongodb 因为高性能、高可用性、支持分片等特性&#xff0c;作为非关系型数据库被大家广泛使用。其高可用性主要是体现在 mongodb 的副本集上面&#xff08;可以简单理解为一主多从的集群&#xff09;&#xff0c;本篇文章主要从副本集介绍、docker搭建…

blender渲染时导致cpu高负载的可能因素

Blender 在进行渲染时&#xff08;尤其是在使用 Cycles 渲染引擎时&#xff09;通常会导致 CPU 高负载的原因主要有以下几个&#xff1a; 渲染计算&#xff1a;Blender 的 Cycles 渲染引擎是一种基于光线追踪的渲染引擎&#xff0c;它通过追踪光线在场景中的传播来生成图像。这…

基于SSM的“口腔护理网站”的设计与实现(源码+数据库+文档)

基于SSM的“口腔护理网站”的设计与实现&#xff08;源码数据库文档) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SSM 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 首页 用户注册页面 医生信息查看模块 口腔护理预约模块 后台首页面…

分享如何通过定时任务调用lighthouse前端测试脚本+在持续集成测试中调用lighthouse前端测试脚本

最近写了个小工具来优化lighthouse在实际工作中的使用&#xff0c;具体实现了&#xff1a;通过定时任务调用前端测试脚本在持续集成测试中调用前端测试脚本。由于在公司中已经应用&#xff0c;所以就不能提供源码了&#xff0c;这里简单说一下实现思路&#xff0c;希望可以帮助…

Java 循环结构 - for, while 及 do...while

Java 循环结构 - for, while 及 do…while 顺序结构的程序语句只能被执行一次。 如果您想要同样的操作执行多次&#xff0c;就需要使用循环结构。 Java中有三种主要的循环结构&#xff1a; while 循环 do…while 循环 for 循环 在 Java5 中引入了一种主要用于数组的增强型 f…

前端面试题日常练-day04 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末。 1. 下列哪个 CSS 单位可以根据用户的首选字体大小进行调整&#xff1f; A) pxB) emC) remD) vw2. HTML5 中的<video>元素用于什么&#xff1f; A) 播放音频文件B) 嵌入外部网页内容C) 显示图…

Debezium日常分享系列之:Debezium 2.7.0.Alpha2发布

Debezium日常分享系列之&#xff1a;Debezium 2.7.0.Alpha2发布 新功能和改进1.Oracle ROW_ID 包含在更改事件中2.带有 JDBC 接收器的 PostreSQL 数组3.Oracle 使用自定义模式名称刷新表4.使用 JWT/seed 进行 NATS 身份验证5.Oracle 大量表查询过滤器 新功能和改进 1.Oracle R…