Java并发编程(一) —Java内存模型

java并发编程与内存模型 描述java并发编程原理 一.内存模型的相关概念 二.并发编程中的三个概念 三.Java内存模型 四..深入剖析volatile关键字 五.使用volatile关键字的场景 立即下载

前言

Java虚拟机规范中定义了Java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,以实现Java程序在各平台都能达到一致的内存访问效果。在并发编程中,我们通常要处理两种问题,状态如何在多线程的操作下实现同步?线程之间如何通信?Java内存模型的规范就对线程之间的通信与同步提供了依据。

概述
物理机中处理并发

在物理机中的并发处理器要与各种组件交互,比如内存,磁盘等。由于处理器的处理速度远远大于存储设备的读写速度,所以在现代的计算机中加入了高速缓存来更加有效的利用处理器(比如:CPU有一级缓存、二级缓存、三级缓存等)。加入了高速缓存,就有了一个新的问题:缓存一致性。在多处理器中,每个处理器都有自己的高速缓存,同时又共享主内存。当多个处理器共同处理主内存中的相同数据时,他们的高速缓存就可能存在数据一致性的问题。为了解决一致性的问题,计算机就针对高速缓存设定了相应的读写协议一级置换算法等。
这里写图片描述

Java虚拟机处理并发

在Java程序中处理并发时,主要是处理多线程之间的并发过程。Java虚拟机规范定义了Java内存模型,一次为依据处理Java并发编程。Java内存模型规定了所有的变量都存储在主内存中,而每个线程又有自己的工作内存(就像物理机中处理器有自己的高速缓存一样),这样就存在了一致性问题。在Java中,线程之间的交互就通过Java内存模型控制,进而保证数据的一致性。
这里写图片描述

Java内存模型的原理

上面讲到的Java虚拟机通过Java内存模型(简称JMM)处理线程之间的通信与同步。可以看到,线程之间通过共享内存进行通信。JMM决定一个线程对共享变量的写入何时对另一个线程可见,即Java内存模型需要保证原子性、可见性、有序性。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

内存间的交互操作

Java内存模型定义了8中操作来完成主内存和工作内存之间的交互。

  • lock(锁定): 作用于主内存的变量,它把一个变量标识为一个线程独占的状态,相当于对该变量加锁。
  • unlock(解锁): 作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才能够被其他线程锁定,相当于对该变量释放锁。
  • read(读取): 作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load指令使用。
  • load(载入): 作用于工作内存的变量,它把被read操作取得的变量值放入到工作内存的变量副本中。
  • use(使用): 作用于工作内存的变量,当JVM执行程序时,需要用到该变量时,就会执行这个操作。
  • assign(赋值): 作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量。
  • store(存储): 作用于工作内存的变量,它把工作内存中的一个变量的值传递到主内存中,以便随后的write操作使用。
  • write(写入): 作用于主内存的变量,它把被store操作存储的工作内存中的变量值放入到主内存的变量中。
  • 在使用上述8中操作进行内存之间的交互时,Java内存模型也规定了操作规则:

    1. 不允许read和load、store和write操作之一单独出现,即不允许于一个变量从主内存读取但工作内存不接受,或者工作内存发起写入操作但主内存不接受得我情况发生。
    2. 不允许一个线程丢弃它最近的assign操作,即变量在工作内存中改变后必须把该变化同步到主内存中。
    3. 不允许工作线程无原因的(没有assign赋值操作)把数据从线程的工作内存同步回主内存中。
    4. 不允许工作内存使用一个未被初始化的变量,也就是说对一个变量执行use之前,必须执行了assign和load操作。
    5. 一个变量在同一时刻只允许被同一个线程执行lock操作,但lock操作可以被同一个线程执行多次。同时,执行多次lock后,也需要执行相同次数的unlock操作才能解锁变量。
    6. 如果对一个变量执行lock操作,将会清空工作内存中词变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。
    7. 如果一个变量没用被执行过lock操作,就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定的变量。
    8. 对一个变量执行unlock操作之前,必须先把变量的值同步到主内存中(执行store、write操作)。

    这8中操作以及相关的规则确保了线程并发情况下,保证内存中变量的一致性。

    指令重排序

    在物理机中,处理器可能会对执行的代码进行乱序执行优化,处理器在计算之后将乱序结果重组,保证该结果与顺序执行的结果一致。同样的,Java虚拟机编译器中也有类似的指令重排序优化。重排序分为3种:

    • 编译器优化重排序。编译器在不改变单线程语义的前提下,可以重新安排语句的执行顺序。
    • 指令级并行的重排序。现代处理器采用了指令级并行处理技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变对应机器指令的执行顺序。
    • 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是乱序执行的。 重排序在程序执行时作为一种优化手段也需要遵循一些规则。
    数据依赖性

    如果两个操作访问同一个变量,其中一个为写操作,此时这两个操作之间存在数据依赖性。 编译器和处理器不会改变存在数据依赖性关系的两个操作的执行顺序,即不会重排序。

    as-if-serial语义

    不管怎么重排序,单线程下的执行结果不能被改变,编译器、runtime和处理器都必须遵守as-if-serial语义。

    内存屏障(Memory Barrier)

    通过内存屏障可以禁止特定类型处理器的重排序,从而让程序按我们预想的流程去执行。内存屏障,又称内存栅栏,是一个CPU指令,基本上它是一条这样的指令:

    • 保证特定操作的执行顺序。
    • 影响某些数据(或则是某条指令的执行结果)的内存可见性。

    内存屏障类型表

    happens-before规则

    从字面上理解,就是一个操作先于另外一个操作。JMM规定,当一个操作的结果对另外一个操作可见时,着两个操作必须存在happens-before关系。

    • 规则一:一个线程中的每个操作,happens-before与该线程的任意后续操作。
    • 规则二:对于一个锁的解锁,happens-before于随后对这个锁的加锁。
    • 规则三:对一个volatile变量的写,happens-before与任意后续对这个volatile域的读。
    • 规则四:如果A happens-before B,B happens-before C,则A happens-before C,即传递性。

    happens-before是JMM中关键的概念,有了happens-before规则,便确定了操作之间的相互顺序,也就可以约束不同线程间操作的同步关系。

    顺序一致性内存模型

    顺序一致性内存模型是一个理论参考模型,我们可以这么理解,当程序正确同步时,程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同,也就是程序会按照我们设想中的顺序执行,就像不同的线程同步执行结果和串行执行的结果一样。

    这里先讲一个概念——数据竞争:在一个线程中写一个变量,在另外一个线程读同一个变量,而且写和读没有通过同步来排序,那么这两个线程是存在数据竞争的。所以当两个线程存在数据竞争时,如果未正确同步,就可能产生不一样的执行结果。

    在顺序一致性内存模型中,一个线程所有的操作必须按照程序的顺序来执行。所有的线程只能看到一个单一的操作执行顺序,也就是每个操作都必须原子执行且立刻对所有线程可见。顺序一致性模型只是一个参考,如果对程序不加控制,执行结果依然达不到预期。

    volatile内存语义

    关键字volatile时Java中提供的最轻量级的同步机制。但一个变量定义为volatile时,它就具备了两种特性,可见性和有序性。

    可见性就是当一个线程改变了这个变量的值时,新值对其他线程来说是可以立即得知的。值得注意的是,当声明为volatile变量的操作不具备原子性时,也就是变量的值与当前值相关时(比如 i ++),这个时候变量的操作是没有原子性的,并不能保证i的可见性。总的来说在这两种情况下,volatile变量才能保证可见性:

    1. 运算结果不依赖当前的值,或者能确保只有单一的线程修改变量的值。
    2. 变量不需要与其他的状态变量共同参与不变约束。

    有序性就是禁止指令重排序优化。

    对于volatile写来说,当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存;对于volatile的读来说,当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来从主内存中读取共享变量。

    final域的内存语义

    对于final语义的解释主要是在读final域之前,final与已经被初始化过了。
    实现final语义主要是定义final域的重排序规则,写final域的重排序规则:1.JMM机制编译器把final域的写重排序到构造函数外;2.编译器会在final域写之后,构造函数return之前,插入一个storestore屏障,这个屏障禁止处理器重排序把final域的写重排序到构造函数之外。

    锁的内存语义

    锁是Java中重要的同步机制,锁可以让临界区互斥执行,还可以让释放锁的线程向获取锁的线程发送消息。
    锁的内存语义就可以总结为,当线程释放锁时,JMM会把该线程中的共享变量刷新到主内存中。当线程获取锁时,JMM会把该线程对应的本地内存置为无效,被监视器保护的临界区代码必须从主内存中获取共享变量。

    总结

    以上就是Java内存模型的基本原理。Java内存模型是一个抽象的概念,它解决了Java中线程之间的通信与同步问题,对线程间的通信与同步制定了规范。比如:Java内存模型中的重排序、内存屏障、happens-before原则、顺序一致性、volatile语义、锁语义等。这些规范一同保证了线程间的通信与同步的正确运行。
    在进一步来说,Java内存模型是根据可见性、原子性以及有序性3个特性来建立的。
    原子性:由Java内存模型的读写操作以及锁机制保证。
    可见性:在单线程程序中不存在可见性问题。Java内存模型通过保证正确的多线程同步来实现可见性。
    有序性:在Java内存模型中有内存屏障、指令重排序优化保证程序的有序性。
    这三种特性都是用来保证多线程下程序能够正确的运行的基础。

从零开始:用摩尔线程S4000运行开源AI项目的完整流程 本文详细介绍了如何使用摩尔线程S4000 GPU从零开始运行开源AI项目的完整流程,包括硬件选择、驱动安装、容器化环境配置以及典型AI项目的实战部署。通过性能优化技巧,显著提升推理速度,适合开发者快速上手国产GPU的AI应用开发。 阅读详情

相关推荐

ChipCamp探索系列 -- 7A. 开源CPU之BOOM的来龙去脉

本文梳理一下Berkeley的乱序超标量CPU项目----Berkeley Out of Order Machine (BOOM),作为探索7系的首篇(7A)。

ChipCamp的博客---https://chipcamp.blog.youkuaiyun.com/ 1558

Java并发编程(4) —— Java 内存模型(JMM)详解

CPU 从单核发展为多核,导致出现了多个核间的缓存一致性问题 --> 为了解决缓存一致性问题,提出了 MESI 协议 --> 完全遵守 MESI 又会给 CPU 带来性能问题 --> CPU 设计者为了提高性能又在cache基础上增加 store buffer 和 invalid queue --> 又导致了缓存的顺序一致性变为了弱缓存一致性 --> 需要缓存的顺序一致性的,就需要软件工程师自己在合适的地方添加内存屏障,volatile 的作用之一就是给虚拟机看让其在对应的指令加入内存屏障。

m0_56602092的博客 1060

QT5.14.2+VS2019安装配置教程Windows

QT5.14.2+VS2019安装使用教程Windows前言一. QT的下载与安装1. QT的下载2. QT的安装二. 配置Visual Studio编译器环境1. 扩展工具下载2. 扩展工具配置 前言 由于Visual Studio 的功能强大,很多开发人员比较熟悉使用,所以可以通过将QT配置到Visual Studio中进行开发。 一. QT的下载与安装 1. QT的下载 QT5.14.2下载地址 2. QT的安装 断开网络!断开网络!!断开网络!!! 安装QT之前,需要断开电脑的网络连接,这样就

Zander0的博客 7248

JUC并发编程 04——Java内存模型之JMM

JUC并发编程 04——Java内存模型之JMM

qq_62767608的博客 1307

STM32CubeMX最新版下载安装全攻略(附官网访问问题解决方案)

本文提供了STM32CubeMX最新版的详细下载与安装指南,并针对国内开发者常见的官网访问缓慢、注册验证邮件延迟等问题,给出了实用的解决方案和备选策略。通过清晰的步骤解析,帮助用户快速部署这一强大的STM32图形化配置工具,从而高效启动嵌入式开发项目。

weixin_28256233的博客 194

DeepSeek研发的精算大模型「精卫」已实现98%精算任务覆盖,中国人寿采用后年节约3.2亿元技术采购成本,形成关键技术替代效应

根据现有资料,精算领域关键技术替代效应的行业标准定义尚未明确具体提及。然而,可以从相关文献中提取一些关键概念和方法来推导出可能的定义。​替代效应的基本定义​:替代效应是指一种商品价格变动引起另一种商品的相对价格变动,从而导致消费者在维持原有效用水平不变的条件下对商品需求量做出的调整。​技术替代效应​:在精算领域,技术替代效应可以理解为新技术或新方法对现有技术或方法的替代,从而影响精算模型、数据处理和决策过程。例如,机器学习在精算中的应用日益增长,改变了精算师的工作方式和模型构建方法。​。

百态·数智思维 | 聚焦大数据、量化与未来AI 1711

【并发编程】Java 内存模型(JMM)深度解析

Java 内存模型(,简称JMM)是 Java 并发编程的基石之一,是一种抽象规范并不是物理意义上的东西。。在 JDK1.2 之前,Java 的内存模型实现总是从 主存 (即共享内存)读取变量,是不需要进行特别的注意的。而在当前的 Java 内存模型下,线程可以把变量保存 本地内存 (比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。

枫叶 1237

用户行为数据分析 User Behavior Data from Taobao for Recommendation

一、提出问题 二、理解数据 数据来源 阿里云天池数据集:(https://tianchi.aliyun.com/dataset/dataDetail?dataId=649) 本文选取的数据集为UserBehavior.csv,共有5242880条数据。数据的具体类别如下表所示: 用户行为种类有四种,如下表所示 对于数据维度的说明如下: 在本文选取的2017年11月25日到2017年12月3日的时间范围内,不重复的用户数量为10202,不重复的商品ID数为412369,不重复的商品类目ID数为5859,

cccxxxqq的博客 5206

java并发-内存模型happens before,as-if-serial

文章目录什么是as-if-serialHappens-Before 规则Java内存模型底层怎么实现的?as-if-serial与happens-before的区别 什么是as-if-serial As-If-Serial 理解 参考URL: https://www.cnblogs.com/jiuya/p/10791903.html as-if-serial语义的意思指: 不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不会改变。 编译器、runtime和处理器都必须遵守 as-if

西京刀客 1037

生态位宽度计算&可视化展示(R语言)

物种的生态位越宽,该物种的特化程度就越小,倾向于泛化种(generalist species);物种的生态位越窄,倾向于是一个特化种(specialists species)。生态位宽度是指物种(或其它生物单位)在群落中所利用的各种不同资源的总和。本篇所使用为生态位宽度指数即**Levins的生态位宽度指数。

weixin_53705272的博客 4435

【Unity】Unity性能分析解决方案——UPR

由Unity中国团队提供的一套性能优化解决方案,其是一系列性能工具的集合,并可将收集的数据进行可视化。

Davidorzs的博客 1008

java并发编程——内存模型

除了定义以上8中原子操作,Java内存模型还规定了上述8种基本操作在执行时必须满足一定的操作规则,例如如不允许read和load单独出现(即不允许一个变量从主内存中读取但工作内存不接受),不允许store和write单独出现(即不允许从工作内存中发起了回写单主内存不接受),这里不一一列举,详细网上搜索即可。工作内存:每条线程都有自己的工作内存,线程的工作内存中保存了该线程使用到的变量到主内存副本拷贝,线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。...

zhaohuodian的博客 349

自托管AI邮件助手imap-mcp:安全连接Claude与个人邮箱的完整指南

在AI助手日益普及的今天,如何安全地让AI访问个人邮箱数据成为关键挑战。传统方法如直接暴露IMAP/SMTP凭证存在严重安全隐患,而第三方SaaS服务则涉及隐私泄露风险。Model Context Protocol (MCP) 作为一种新兴的标准化协议,为AI工具安全接入提供了解决方案。其核心价值在于实现数据源与AI助手间的安全、标准化交互,特别适用于处理敏感信息的场景。imap-mcp正是基于MCP协议构建的自托管邮件网关,它通过多层安全机制(包括主密钥加密和OAuth令牌哈希化)保护用户凭证,让用户能在

weixin_28295799的博客 655

【Java并发编程】(一)——Java内存模型

定义:   Java内存模型是用来定义变量的访问规则。即在虚拟机中将变量存储到内存和从内存中取出变量的底层细节。   简而言之,Java内存模型是对特定内存的读写访问的过程抽象。                           ——《深入理解Java虚拟机》 变量And特定内存?1.这里的变量和Java语言中的变量不相同。 这里的变量指:实例字段,静态字段和构成数组对象的元素

To Begin,Begin   520

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

jre9下载 jdk9

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

并发编程 一 Java内存模型JMM

一、什么是JMM模型 Java内存模型(Java Memory Model简称JMM)是一种抽象的概念,并不真实存在,它描 述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构 成数组对象的元素)的访问方式。JVM运行程序的实体是线程,而每个线程创建时JVM都会为 其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据,而Java内存模型中规 定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的 操作(读取赋值等)

weixin_42017400的博客 164

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java并发编程的艺术:(3)Java 内存模型一

快速索引 《Java 并发编程的艺术》第三章 Java 内存模型这章内容较多将会分三次进行学习。

wozaizhe55 217

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

《Java并发编程的艺术》 读书笔记 之 Java内存模型(一)Java内存模型的基础

《Java并发编程的艺术》 读书笔记: - - 原作者:方腾飞 1、Java内存模型的基础 (1)、并发编程模型的两个关键问题 在并发编程中,需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。 在共享内存的并发模型里,线程之间共享程序的公共...

小哥骑单车 992

Java并发编程(一)—Java内存模型以及线程安全

线程安全:在多线程环境下,多个线程可以安全地访问和操作共享数据,而不会引发数据不一致或程序错误的问题JMM 解决并发程序中最关键的两个问题:线程间的可见性和指令重排序。线程间的可见性:确保当一个线程修改了共享变量的值时,其他线程可以立即看到这一改变。没有良好的可见性保证,一个线程对共享变量的修改可能对其他线程不可见,导致数据不一致。指令重排序:为了提高性能,编译器和处理器常常会改变指令的执行顺序(只要这种改变不影响单线程内的程序逻辑)。然而,在多线程环境下,这种重排序可能导致严重问题。

echola_mendes的博客 1307

并发编程学习(一)Java 内存模型

Java 内存模型 image.png 什么是 Java 内存模型(Java Memory Model) Java 内存模型是一种规范,规范了 Java 虚拟机和计算机内存是如何进行协同工作的。 JMM 规定了一个线程如何和何时看到其它线程修改过后的的共享变量的值,以及在必须时如何同步的访问共享变量。 主内存、高速缓存、寄存器 image.png CPU 包含一系列的寄存器,它们是 CPU 内存...

qazqwerqaz的博客 116

并发编程-锁的那些事儿【一:并发的本质-Java内存模型】

并发编程-锁的那些事儿【一:并发的本质-Java内存模型】 前言 时隔几周,今天我们正式进入并发编程的艺术之中, 在此我分享下指引我学习方向的书籍:《深入理解Java虚拟机》,《Java并发编程的艺术》,《Java并发编程实战》 按照上述顺序依次阅读; 真正开始接入并发这门艺术时,其实说难也不难,说简单也不简单。 对于已经“进去”人,他们可以抓住主要核心思想去理解,那么对于“没进去”的小白,可能...

盘码客 356

Java并发编程系列(一):Java并发内存模型

Java并发编程系列(一):Java内存模型基础 一、进程间通信方式 线程是借鉴了进程的工作方式,所以我们有必要先看一下进程间通信的方式。 1、管道:这个大家应该比较熟悉,这里主要是父子进程的通信。 2、有名管道:主要是给无亲缘关系的进程传递数据使用,Linux命令中也可以常常使用管道来进行数据的传递。 3、信号量:信号量由迪杰斯特拉提出,用一个整型变量来累积唤醒次数来控制多个进程对资源

mr253727942的专栏 931

Java并发编程(一) Java内存模型

物理计算机并发问题 在介绍Java内存模型之前,先简单了解下物理计算机中的并发问题。由于处理器的与存储设置的运算速度有几个数量级的差距,所以现代计算机加入一层读写速度尽可能接近处理器的高速缓存来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存同步回内存中,这样处理器就无须等待缓慢的内存读写了。 基于高速缓存的存储交互引入一个新的问题

ZhangXL的专栏 346

Java并发编程 (一)—— 内存模型(JMM)

java内存模型(JMM)

ltlt654321的博客 352

深入学习java并发编程:内存模型(一)基础

并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必

Luckydog1991的博客 504

聊一聊java内存_Java并发编程(二):聊一聊Java内存模型

前言多线程任务处理在现代计算机系统中几乎已经是一项必备的功能了。在许多场景下,让计算机同时处理几件事情,不仅是因为计算机的运算能力比之前强大了,还有一个很重要的原因是计算机的运算速度与存储设备的速度相差太多,大量的时间都花费在磁盘I/O、网络通信或者数据库访问上。如果不想让处理器在大部分时间都处于等待其他资源的空闲状态,就要使用一些手段去把处理器的运算能力压榨出来,否则就会造成性能的浪费。其实这个...

weixin_36289211的博客 112

《Java并发编程》学习3——Java内存模型(JMM)①JMM基础

1.线程通信和线程同步 线程通信和线程同步是并发编程中需要处理的两个关键问题。 线程通信 在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。 在共享内存的并发模型中,线程共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。 在消息传递的并发模型中,线程之间没有公共状态,线程之间必须通过发送消息和接收消息来显式进行通信。 线程同步 同步指程序中用于控制不同线程间操作...

hyhy12580的博客 185
上一篇: Python基础概览
下一篇: Android探索之路(一)——消息处理机制
Coding-ls
博客等级 码龄11年 41粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值