详解Java多线程开发中的数据同步

Java多线程编程详解 本文系统介绍了Java多线程编程的核心内容,包括线程创建方式(继承Thread类、实现Runnable/Callable接口、线程池)、生命周期管理、同步机制(synchronized、Lock、volatile、原子类)以及常用并发工具类(CountDownLatch、CyclicBarrier、Semaphore)。通过代码示例展示了各种多线程技术的实际应用,帮助开发者理解并发编程的关键概念和技术实现。文章涵盖从基础到进阶的多线程知识,为Java开发者提供了全面的并发编程指导。 阅读详情

Java中的变量分为两类:局部变量和类变量。局部变量是指在方法内定义的变量,如在run方法中定义的变量。对于这些变量来说,并不存在线程之间共享的问题。因此,它们不需要进行数据同步。类变量是在类中定义的变量,作用域是整个类。这类变量可以被多个线程共享。因此,我们需要对这类变量进行数据同步。

 

数据同步就是指在同一时间,只能由一个线程来访问被同步的类变量,当前线程访问完这些变量后,其他线程才能继续访问。这里说的访问是指有写操作的访问,如果所有访问类变量的线程都是读操作,一般是不需要数据同步的。

 

那么如果不对共享的类变量进行数据同步,会发生什么情况呢?让我们先看看下面的代码会发生什么样的事情:

package test;
public class MyThread extends Thread
 {
   public static int n = 0;
   public void run()
    {
      int m = n;yield();
      m++;n = m;
    }
   public static void main(String[] args) throws Exception
   {
    MyThread myThread = new MyThread ();
    Thread threads[] = new Thread[100];
    for (int i = 0; i < threads.length; i++)threads[i] = new Thread(myThread);
    for (int i = 0; i < threads.length; i++)threads[i].start();
    for (int i = 0; i < threads.length; i++)threads[i].join();
    System.out.println("n = " + MyThread.n);
   }
}

 

在执行上面代码的可能结果如下:

 

n = 59

 

看到这个结果,可能很多读者会感到奇怪。这个程序明明是启动了100个线程,然后每个线程将静态变量n加1.最后使用join方法使这100个线程都运行完后,再输出这个n值。按正常来讲,结果应该是n = 100。可偏偏结果小于100。

 

其实产生这种结果的罪魁祸首就是我们经常提到的“脏数据”。而run方法中的yield()语句就是产生“脏数据”的始作俑者(不加yield语句也可能会产生“脏数据”,但不会这么明显,只有将100改成更大的数,才会经常产生“脏数据”,在本例中调用yield就是为了放大“脏数据”的效果)。yield方法的作用是使线程暂停,也就是使调用yield方法的线程暂时放弃CPU资源,使CPU有机会来执行其他的线程。为了说明这个程序如何产生“脏数据”,我们假设只创建了两个线程:thread1和thread2.由于先调用了thread1的start方法,因此,thread1的run方法一般会先运行。当thread1的run方法运行到第一行(int m = n;)时,将n的值赋给m.当执行到第二行的yield方法后,thread1就会暂时停止执行,而当thread1暂停时,thread2获得了CPU资源后开始运行(之前thread2一直处于就绪状态),当thread2执行到第一行(int m = n;)时,由于thread1在执行到yield时n仍然是0,因此,thread2中的m获得的值也是0.这样就造成了thread1和thread2的m获得的都是0.在它们执行完yield方法后,都是从0开始加1,因此,无论谁先执行完,最后n的值都是1,只是这个n被thread1和thread2各赋了一遍值。这个过程如下图如示:

 

也许有人会问,如果只有n++,会产生“脏数据”吗?答案是肯定的。那么n++只是一条语句,又如何在执行过程中将CPU交给其他的线程呢?其实这只是表面现象,n++在被Java编译器编译成中间语言(也叫做字节码)后,并不是一条语言。让我们看看下面的Java代码将会被编译成什么样的Java中间语言。

 

Java源代码

public void run()
{
n++;
}
被编译后的中间语言代码 
001  public void run()
002  {
003  aload_0 
004  dup 
005  getfield
006  iconst_1
007  iadd
008  putfield   
009  return  
010  }

 

大家可以看到在run方法中只有n++一条语句,而在编译后,却有7条中间语言语句。我们并不需要知道这些语句的功能是什么,只看一下第005、007和008行语句。在005行是getfield,根据它的英文含义可知是要得到某个值,因为这里只有一个n,所以毫无疑问,是要得到n的值。而在007行的iadd也不难猜测是将这个得到的n值加1.在008行的putfield的含义我想大家可能已经猜出来了,它负责将这个加1后的n再更新回类变量n.说到这,可能大家还有一个疑惑,执行n++时直接将n加1不就行了,为什么要如此费周折。其实这里涉及到一个Java内存模型的问题。

 

Java的内存模型分为主存储区和工作存储区。主存储区保存了Java中所有的实例。也就是说,在我们使用new来建立一个对象后,这个对象及它内部的方法、变量等都保存在这一区域,在MyThread类中的n就保存在这个区域。主存储区可以被所有线程共享。而工作存储区就是我们前面所讲的线程栈,在这个区域里保存了在run方法以及run方法所调用的方法中定义的变量,也就是方法变量。在线程要修改主存储区中的变量时,并不是直接修改这些变量,而是将它们先复制到当前线程的工作存储区,在修改完后,再将这个变量值覆盖主存储区的相应的变量值。

 

在了解了Java的内存模型后,就不难理解为什么n++也不是原子操作了。它必须经过一个拷贝、加1和覆盖的过程。这个过程和在MyThread类中模拟的过程类似。大家可以想象,如果在执行到getfield时,thread1由于某种原因被中断,那么就会发生和MyThread类的执行结果类似的情况。要想彻底解决这个问题,就必须使用某种方法对n进行同步,也就是在同一时间只能有一个线程操作n,这也称为对n的原子操作。

Java多线程开发中的数据同步 接口,我们可以确保在多线程环境下对共享数据的访问是同步的。在使用这些机制时,需要注意锁的粒度和释放,以避免死锁和资源竞争等问题的发生。在后端开发中,多线程编程是非常常见的需求。然而,多线程环境下的数据同步问题也是一个需要注意和解决的重要问题。本文将详细介绍在Java多线程开发中如何进行数据同步,并提供相应的源代码示例。接口时,我们需要手动释放锁,确保在发生异常等情况下锁的释放。在Java多线程开发中,数据同步是一个需要重视的问题。机制外,Java还提供了其他一些用于数据同步的工具类,比如。 阅读详情

相关推荐

分布式存储系统关于GDPR条例中的数据清除原则

文章目录前言HDFS存储系统数据的完全删除基于加解密的输入输出流的数据保护方案 前言 关于GDPR是什么,可能许多同学之前并不太了解,至少笔者在之前也是不清楚的。GDPR全称为通用数据保护条例,General Data Protection Regulation。它是一项来自欧盟的关于计算机数据保护相关的条约,旨在规范系统如何收集,管控用户私人数据的种种行为。但是当前的一些存储系统并没有完全符合...

走在前往架构师的路上 3624

菜鸟课堂:详解Java多线程开发中的数据同步

                                         来源:chinaitlab    作者:chinaitlab Java中的变量分为两类:局部变量和类变量。局部变量是指在方法内定义的变量,如在run方法中定义的变量。对于这些变量来说,并不存在线程之间共享的问题。因此,它们不需要进行数据同步。类变量是在类中定义的变量,作用域是整个类。这类变

优雅的IT之道 2455

SAP-ABAP:SAP ABAP 深度解析:BAPI 从入门到精通 —— 原理、实战与自定义开发全指南

SAP ABAP BAPI 深度解析摘要 本文全面介绍了 SAP ABAP 中的 BAPI(业务应用程序编程接口)技术,涵盖以下核心内容: BAPI 定义与特点:BAPI 是 SAP 为业务对象提供的标准化编程接口,具有面向对象、封装业务逻辑、标准化错误处理和版本兼容性等特点。 BAPI 与 RFC 关系:所有 BAPI 都是 RFC,但需额外满足业务对象注册、标准化参数和错误处理等要求。 BAPI 核心作用:包括业务逻辑封装、系统集成、标准化错误处理、版本兼容和审计合规。 实战演示:通过创建销售订单的完整

baidu_35680696的博客 1033

自动驾驶——为什么需要仿真?

想象一下当你发现了一个新的算法,但还不确认它是否有效,你是否会直接找一辆自动驾驶汽车,更新软件,并且进行测试呢?这样做可能并不安全,你必须把所有的场景测试一遍以保证它足够好,这可需要大量的时间。仿真的好处显而易见,它通过软件模拟来发现和复现问题,而不需要真实的环境和硬件,可以极大的节省成本和时间。 随着现在深度学习的兴起,仿真在自动驾驶领域有了新的用武之地。自动驾驶平台通过仿真采集数据,可以把训练时间大大提高,远远超出路测的时间,加快模型迭代速度。先利用集群训练模型,然后再到实际的路测中去检验,采用数据驱动

kk阿彬 1341

FreeRTOS OTA实战:从Bootloader设计到安全升级的完整流程(附MQTT示例代码)

本文详细介绍了在FreeRTOS系统中实现安全OTA固件升级的完整流程。内容涵盖从Bootloader设计、存储分区规划到与MQTT协议集成的OTA Agent任务开发,并重点解析了固件签名验证、防回滚等关键安全机制,为嵌入式物联网设备提供了一套高可靠性的远程升级解决方案。

weixin_29248653的博客 161

AD23导出Gerber文件保姆级教程:从PCB到嘉立创下单,一步不落(附常见问题排查)

本文提供AD23导出Gerber文件的详细教程,涵盖从PCB设计检查到嘉立创下单的全流程,特别针对两层板设计场景,帮助新手工程师避免常见错误。内容包括Gerber文件生成步骤、钻孔文件设置、文件检查工具推荐以及嘉立创下单实操指南,确保PCB打样顺利。

weixin_30924239的博客 440

static 全局变量与普通的全局变量有什么区别

http://wenku.baidu.com/view/be039ec184254b35eefd341b.html

u011248345的专栏 1335

海洋科学—物理海洋学 第五章 海洋环流

本章是基于《海洋科学导论》,但里面涉及到的重要的公式推导是专门拎出来推的,主要借鉴董昌明老师的《物理海洋学导论》,其中有一些多出来的推导,会在更新完整个物理海洋学之后重新拿出来一一讲解,最后开一个番外篇

qq_58518586的博客 1万+

数据同步是如何实现的?为什么需要数据同步?

实时数据同步,确保数据的一致性和实时更新性,将有利于企业各部门之间高效协作,从而支持企业的业务运作和决策。本文将介绍数据同步概念、数据同步的步骤、数据同步的方式,从而加深对数据同步的认识。

oOBubbleX的博客 2381

交换机四种光互联技术:OIO、OBO、NPO与CPO

在过去几十年里,数据中心交换机主要依赖电信号通过铜线进行数据传输。然而,随着数据传输速率从100Gbps向400Gbps、800Gbps甚至1.6Tbps迈进,传统电互联(Electrical Input & Output, EIO)面临三大瓶颈:信号衰减、功耗激增和空间限制。例如,高速信号在长距离铜线传输中会产生严重的信号失真,迫使设计者加入数字信号处理器(DSP)来补偿信号衰减,这进一步推高了功耗和成本。此外,传统可插拔光模块的体积较大,限制了端口密度,难以满足现代数据中心对高带宽密度的需求。

网络技术联盟站 3134

YOLOv13全网首发:CVPR2026 MixerCSeg | DEGConv方向引导边缘门控,破解细长裂缝检测难题

DEGConv通过方向先验嵌入、边缘增强卷积和动态门控三大机制,针对性解决了YOLO在处理裂缝类细长、多方向、低对比度目标时的特征提取不足问题,显著提升了裂缝检测的精度与鲁棒性。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 441

java调用datax实现不同数据库的表的同步

最近工作中需要对不同数据库中的两个表的数据进行同步,然而本菜鸡只会先将表里的数据清空,让后通过@DS注解查询另一张表的数据插入到被清空的表中。本来,代码都写完了,开始运行。哦嚯,由于命名规范,两个表的名称不一样,报错了,找不到那张表。但字段都是一样的,为此再写一个实体,加上@TableName注解又不太合适。前辈告诉我说,用datax同步数据。 1.下载与使用 一开始,下载的datax的源码,弄了半天不会用。所以直接用现成的吧,下载完解压就行了。 放上链接:datax下载地址 ...

Libra815的博客 4235

打开 AI 投研新时代 —— 深度解析 GitHub 高星项目 daily_stock_analysis

GitHub热门开源项目"daily_stock_analysis"是一款AI驱动的智能股票分析工具,能自动抓取行情数据、分析新闻语义并生成结构化报告。该项目采用Python开发,通过GitHub Actions实现全自动运行,支持邮件、企业微信等多渠道推送。核心功能包括AI决策仪表盘、多数据源整合和零成本部署方案,特别适合需要自动化投研辅助的个人投资者。项目强调其仅为分析工具而非投资建议,提醒用户注意AI模型的潜在误差。该工具通过智能化处理重复工作,帮助投资者提升决策效率,成为量化投资

陈奕昆的博客 1526

java 多线程 数据同步_详解Java多线程开发中的数据同步

Java中的变量分为两类:局部变量和类变量。局部变量是指在方法内定义的变量,如在run方法中定义的变量。对于这些变量来说,并不存在线程之间共享的问题。因此,它们不需要进行数据同步。类变量是在类中定义的变量,作用域是整个类。这类变量可以被多个线程共享。因此,我们需要对这类变量进行数据同步。数据同步就是指在同一时间,只能由一个线程来访问被同步的类变量,当前线程访问完这些变量后,其他线程才能继续访问。这...

weixin_30230059的博客 449

jre9下载 jdk9

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

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

bo2-About Java 多线程 -------->菜鸟课堂:详解Java多线程开发中的数据同步(unLook!)

 Java中的变量分为两类:局部变量和类变量。局部变量是指在方法内定义的变量,如在run方法中定义的变量。对于这些变量来说,并不存在线程之间共享的问题。因此,它们不需要进行数据同步。类变量是在类中定义的变量,作用域是整个类。这类变量可以被多个线程共享。因此,我们需要对这类变量进行数据同步。   数据同步就是指在同一时间,只能由一个线程来访问被同步的类变量,当前线程访问完这些变量后,其

夏日向日葵的专栏 729

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

JAVA中的多线程详解

进程是一个包含自身执行地址的程序,多线程使程序可以同时存在多个执行片段,这些执行片段根据不同的条件和环境同步或者异步工作,在一个进程内部可以执行多项任务,进程内部的任务被称为线程,线程是进程中的实体,一个进程可以拥有多个线程。多线程是指在一个程序中同时执行多个线程,每个线程都有自己独立的执行路径。在多线程中,程序的执行可以同时进行多个任务,从而提高系统的资源利用率和响应性能。在传统的单线程编程模型中,程序按照顺序执行,一次只处理一个任务。这种方式在某些情况下可能会导致效率低下或者无法满足需求。

2302_79993788的博客 1324

java中的多线程和数据同步问题

编程中有一个经典的多线程问题:有两个线程,一个负责写入数据,一个负责读出数据,当两个线程同步运行时,如何保证数据的准确性和安全性?人们将这一问题抽象成生产者-消费者模型。 //有一个数据模型Person类,包含三个属性以及写入和读取这三个属性的方法。 public class Person { private String name; private String gender; p...

login_at_march_13的博客 812

java 多线程 数据同步,java怎么实现数据的同步-多线程

java如何实现数据的同步--多线程经常会遇到一个这样的问题:如何实现 判断一个内存对象如Vector 是否有数据,如果有数据 就及时的 读取出来?常用的普通方法是 用一个 while()循环 这个 Vector是否有数据,如果有数据 才读取。 但是 这种方法 占用的资源多,效率不高。以下教你 如何 用JAVA的wait(),notify(),notifyAll(),结合多线程来实现 上面的问题...

weixin_35793308的博客 611

Java多线程详解(一)Java多线程入门

最近听很多面试的小伙伴说,网上往往是一篇一篇的Java多线程的文章,除了书籍没有什么学习多线程的一系列文章。但是仅仅凭借一两篇文章很难对多线程有系统的学习,而且面试的时候多线程这方面的知识往往也是考察的重点,所以考虑之下决定写一系列关于Java多线程的文章。文章参考了高老师的《Java多线程编程核心技术》。力争使用最短的篇幅把Java多线程的知识作以系统的讲述。 本节思维导图: 思维导图...

刘成 2475

多线程详解

​​学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。各位小伙伴,如果您:想系统/深入学习某技术知识点…一个人摸索学习很难坚持,想组团高效学习…想写博客但无从下手,急需写作干货注入能量…热爱写作,愿意让自己成为更好的人…...

m0_65144570的博客 2062

Java多线程中的ABA问题详解

ABA问题是在并发编程中出现的一种情况,涉及到多个线程对同一内存位置进行读写操作。它的名字来源于以下操作序列:A → B → A。在这种情况下,线程1读取了一个共享变量的值A,然后线程2将该共享变量的值更改为B,最后线程2又将其值改回A。这个问题会影响基于CAS(Compare-And-Swap)或类似机制的并发算法。在CAS操作中,线程会读取一个内存位置的值,并且只有在该值和预期值相同时才会进行更新操作。ABA问题使得在并发环境中可能会忽略中间发生的其他更改,因为它只检查值是否与预期值相同。举个例子。

EverythingAtOnce的博客 2069

Java多线程数据同步

当多个线程同时读写同一个份数据时其结果可能会和我们期望的结果不一致,例如两个线程对同一个变量做自增,得到的结果和我们想要的可能不一样,示例如下: package com.shaoshuidashi; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Explore { int a = 0; void add(){ a++;.

TARS_的博客 415

Java多线程锁如何进行数据同步共享

Java多线程锁是为了解决数据同步中的数据安全问题,下面我们就来详细的学习下有关于Java多线程锁的相关问题。只有不断的学习才能不断的提高自身的相关技术。 大多数应用程序要求线程互相通信来同步它们的动作。在Java程序中最简单实现同步的方法就是上Java多线程锁。为了防止同时访

barnett_zhubo的专栏 4190

java 多线程 数据同步_java(多线程)实现高性能数据同步

首 先在代码与生产库间建立一个Connection,将读取到的数据放在ResultSet对象,然后再与开发库建立一个Connection。从 ResultSet取出数据后通过TestConnection插入到开发库,以此来实现Copy。代码写完后运行程序,速度太慢了,一秒钟只能Copy 一千条数据,生产库上有上亿条数据,按照这个速度同步完要到猴年马月呀,用PreparedStatement批处理速...

weixin_42486913的博客 845

Java 多线程技术详解

多线程编程的核心优势在于它能够实现任务的并行处理,即在同一时间处理多个任务,这对于处理I/O密集型或计算密集型的工作负载特别有效。

小电玩 2074
上一篇: Java多线程程序设计
优雅的程序员
博客等级 码龄15年 2粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值