[架构之路-122]-《软考-系统架构设计师》-操作系统-1-操作系统原理 - 进程管理:同步VS异步、互斥VS共享、PV操作

目录

前言:

第11章 操作系统

第1节 操作系统概述

第2节 调度程序原理:管理者本身

第3节 进程管理:管理应用程序的机制(CPU)

3.1 进程的状态切换:三态模型 VS 五态模型

3.2 前驱图

3.3 同步与互斥

3.3.1 互斥VS共享:上厕所的两个人 =》 只要求访问共享资源不同时即可,确保不同时

3.3.2 同步VS异步:协作在家做饭招呼客人的两个人 =》 要求两个人操作数据有先后顺序 -》确保同时,确保按照特定顺序

3.3.3 相同点

3.3.4 不同点

3.4 并发相关的基本概念

3.5 PV操作

3.6 进程的死锁

3.6.1 定义

3.6.2 产生条件

3.6.3 有序资源分配法

3.6.4 银行算法

补充材料:

原子操作变量和普通变量

原子操作变量的原理

为什么说普通变量的访问不具备原子性


前言:

操作系统的本质就是创建一个并发的应用程序执行的环境,使得各种应用程序可以动态、共享相同的计算机物理硬件资源,计算机的三大物理资源包括:

  • CPU

  • 内存

  • 外设

应用程序(管理应用程序):以进程和现成的方式组织,所有的应用程序被抽象成了一个个的进程与现成;然后,有了进程间同步、互斥与通信、进程的优先级调度等概念。

所有的外设(管理外设资源):以统一的文件来组织,所有的应用程序通过文件的方式访问所有的外设,操作系统通过把文件映射成设备的驱动程序访问外设硬件。并以中断的手段提供异步抢占的方式临时占用计算机的资源。

所有的内存(管理内存资源)一虚拟地址的方式来组织,每个应用程序拥有0G~3G的用户地址空间和3G~4G的内核专有空间,于是了内存管理、MMU和地址映射等等概念。

内核调度程序(管理CPU资源):如何管理上述资源呢?于是就有了操作系统的调度程序!

本文就是探讨操作系统上述核心理念和原理!!!

第11章 操作系统

第1节 操作系统概述

第2节 调度程序原理:管理者本身

(139条消息) [机缘参悟-96] :软件中到处充满了人类社会的气息!_文火冰糖的硅基工坊的博客-CSDN博客

第3节 进程管理:管理应用程序的机制(CPU)

3.1 进程的状态切换:三态模型 VS 五态模型

3.2 前驱图

前驱图是一种用来描述程序(或进程)之间先后执行顺序的有向无环图(简称DAG, Directed Acyclic Graph)。

前趋图由结点和有向边两部分组成,每个结点表示一个程序、进程、程序段或者一条语句,结点间的有向边表示结点之间的前驱关系。从结点Si到结点Sj的有向边表示它们的前趋关系,记为Si→Sj,即Si和Sj应顺序执行,Sj仅在Si执行完成后才能开始执行。

前驱图(precedence graph)是一种用于表示并发执行的任务或操作之间的依赖关系的有向图。在并行计算、并发编程和调度算法中常用到前驱图来进行任务调度和资源分配等操作。

在前驱图中,节点代表着任务或操作,有向边表示任务之间的依赖关系。如果任务 A 依赖于任务 B 的完成结果,那么前驱图中会有一条从任务 B 指向任务 A 的有向边。这意味着任务 A 的执行必须在任务 B 之后才能开始。

通过构建前驱图,可以通过拓扑排序算法对任务进行有序调度,确保每个任务的依赖关系得到满足。拓扑排序算法可以按照任务之间的依赖关系确定任务的执行顺序,并且保证不会出现循环依赖的情况。

前驱图还可以用于检测任务之间的死锁或资源争用问题。如果前驱图中存在环路,则表示存在循环依赖,任务之间可能会出现死锁通过检测和处理环路,可以避免死锁问题的发生。

总结来说,前驱图是一种用于表示并发任务或操作之间依赖关系的有向图。它可以被用于任务调度、资源分配和死锁检测等并发编程和调度算法中的应用。通过构建和分析前驱图,可以优化任务的执行顺序以及解决并发编程中的竞争和死锁问题。

3.3 同步与互斥

在单CPU、多CPU以及分布式系统中,有多个进程并发甚至并行执行。对资源的共享和竞争使得并发进程之间相互制约,因为该原因通常产生意想不到的错误,且在程序逻辑上体现不出来。

原因:

①由于共享某些资源,(如变量、文件、设备)等,一个进程的执行可能影响其他进程的执行结果。

②与同一共享资源有关的程序段分散在各进程中,而且各进程的相对执行速度不可预知。

③由于每次并发执行速度顺序不同,并发进程的执行结果将不确定(无法再现),甚至可能导致错误;但由于这不可再现的原因,导致bug很难定位排除。

3.3.1 互斥VS共享:上厕所的两个人 =》 只要求访问共享资源不同时即可,确保不同时

互斥:对临界资源的访问。

互斥(Mutex)和共享(Semaphore)是操作系统中常用的同步机制,用于控制对临界资源的访问。它们的主要区别在于如何允许多个线程或进程同时访问资源。

互斥是一种以独占方式来访问共享资源的机制。当一个线程进入临界区时,其他线程必须等待并阻塞,直到该线程退出临界区。这样可以保证在同一时间只有一个线程访问共享资源,从而避免数据竞争和冲突。互斥锁(Mutex Lock)是常见的实现互斥机制的方式。

共享是一种允许多个线程或进程同时访问共享资源的机制。使用共享信号量(Semaphore)来跟踪资源访问的数量,当资源的信号量计数大于零时,允许多个线程或进程访问共享资源。如果信号量计数变为零,后续线程或进程将被阻塞,直到有线程或进程释放资源并增加信号量计数。共享信号量适用于控制资源使用数量的情况。

对于选择使用互斥还是共享,通常取决于资源的特性和访问需求:

  • 互斥适用于对某个资源需要保护独占访问的情况,比如访问共享数据结构、文件、设备等。使用互斥锁可以确保在同一时间只有一个线程能够对资源进行操作,从而避免数据竞争和冲突。
  • 共享适用于资源可以被多个线程或进程同时访问的情况,并且需要限制同时访问的数量。使用共享信号量允许多个线程或进程同时访问资源,但需要根据实际需求对资源的并发访问数量进行适当的控制和调度。

需要注意的是,正确使用互斥和共享机制是确保多线程/多进程程序正确性的关键。错误的同步方式可能导致死锁、竞态条件和数据不一致等问题。在使用互斥和共享机制时,应谨慎设计和实施,遵循同步原则和最佳实践,以确保程序能够正确、高效地处理共享资源。

3.3.2 同步VS异步:协作在家做饭招呼客人的两个人 =》 要求两个人操作数据有先后顺序 -》确保同时,确保按照特定顺序

同步:不同速度线程之间的相互等待。

在上述模型中,生产者与消费者之间通过市场进行缓冲,因此生产者与消费者之间不需要完全同步,生产速度和消费速度可以一定程度的不一致。当生产速度消费速度,就出现生产过程剩,价格就会下降,促使生产者降低生产;当生产速度小于消费速度,就出现生产不足,价格机会出现上升,促使生产者加大生产,最终得到以某种平衡,这就是市场的作用。

在由操作系统管理的两个不同速率的进程之间,也是这种原理,通过中间的缓冲区(如队列、FIFO等)和同步机制,在生产者进程和消费者进程之间进行同步。不过操作系统中,没有引入价格机制,如果能够进入价格机制,这种模型就更接近现实世界了。

同步(Synchronous)和异步(Asynchronous)是描述程序执行模式的概念,用于确定如何处理任务的进行和完成。

同步指的是任务按照顺序逐个执行,并且每个任务必须等待前一个任务(前趋)的完成才能开始执行。在同步模式下,任务的执行是阻塞的,即当一个任务在执行时,其他任务需要等待。同步模式通常用于简单的线性流程,其中任务之间存在依赖关系。

异步指的是任务在后台进行,不需要等待前一个任务的完成,可以继续执行其他任务。在异步模式下,任务的执行是非阻塞的,即一个任务执行时不会影响其他任务的进行。异步模式通常用于复杂的多任务或并发场景,其中任务之间不存在直接的依赖关系。

以下是同步和异步的一些关键区别:

  1. 执行方式:同步任务按顺序逐个执行,每个任务等待前一个任务完成(唤醒)。异步任务在后台并发执行,不需要等待前一个任务完成。
  2. 阻塞行为:同步任务在执行时会阻塞其他后续任务的执行,每个任务的执行时间会影响整体执行时间。异步任务的执行不会阻塞其他任务的进行,每个任务可以独立执行。
  3. 反馈机制:同步任务通过返回值或异常来提供结果和错误信息。异步任务通常使用回调函数、事件或异步通知来处理结果和错误。
  4. 编程模型:同步任务通常使用顺序结构(如函数调用、循环)进行编程。异步任务通常使用回调、Promise、async/await等机制进行编程

选择同步还是异步主要取决于任务的性质和应用场景:

  • 同步适用于任务之间有依赖关系,需要确保任务的顺序执行和结果的一致性。同步模式简单直观,适用于简单的操作和算法,但可能会导致程序阻塞和响应时间延长。
  • 异步适用于需要同时处理多个任务或需要进行非阻塞的操作。异步模式通常用于网络请求、文件操作、GUI应用程序等需要响应性和并发性的场景,但它也可能更加复杂和难以编写和调试。

需要根据具体应用和需求权衡选择同步还是异步,合理利用它们的优势和特点以提高程序的性能和用户体验。一些情况下,同步和异步可以结合使用,例如使用异步任务来执行耗时的操作,以避免阻塞主线程,同时保持关键任务的同步性。

3.3.3 相同点

同步(Synchronization)和互斥(Mutual Exclusion)在并发编程中确实有一些相同的点:

  1. 目标:

    • 同步和互斥的共同目标是确保多个线程能够安全地访问共享资源,并保持数据的一致性
    • 它们都致力于解决并发编程中的竞争条件(Race Condition)和不一致性问题
  2. 实现方式:

    • 同步和互斥都可以通过相同的机制来实现,如锁(例如互斥锁、读写锁)、条件变量等。
    • 无论是同步还是互斥,使用锁来限制线程对共享资源的访问,并且确保在某个时间点只有一个线程能够访问共享资源。
  3. 需要注意的点:

    • 同步和互斥都需要在并发场景下谨慎使用,确保正确性和性能的平衡。过度使用同步和互斥会导致线程之间的竞争条件过多,从而降低程序的并发性能。
    • 在实际应用中,通常需要综合考虑使用同步和互斥的适当方式,以满足数据一致性和共享资源访问的需求。

总结来说,同步和互斥在并发编程中都致力于解决多个线程之间的竞争条件和数据一致性问题。它们可以通过相同的机制实现,如锁,以限制对共享资源的访问,并确保在某个时间点只有一个线程能够访问这些资源。然而,在具体应用中,需要考虑到正确性和性能的平衡,适当地使用同步和互斥机制来满足并发编程的需求。

3.3.4 不同点

同步(Synchronization)和互斥(Mutual Exclusion)是并发编程(多线程、多进程并发)中用于管理共享资源和控制多个线程访问的两种重要机制,它们有以下区别:

  1. 目标:

    • 同步的目标是确保多个线程按照一定的顺序或协作完成任务(通常需要访问共享资源完成相互协作,没有数据交互,就谈不上协作),并保持数据的一致性。同步机制可以用于协调不同线程的操作,使它们按照特定的规则或条件进行有序的执行
    • 互斥的目标是确保多个线程不会同时访问共享资源,但对不同进程访问资源的时间顺序没有要求,只要不同时访问即可,以防止数据竞争和不一致性。互斥机制可以用于保护共享资源,使其在一个时间点只能由一个线程进行访问。
  2. 概念:

    • 同步涉及一组线程之间的协调和通信,以便它们能够以正确的顺序执行,并根据需求等待或唤醒其他线程。
    • 互斥涉及到多个线程之间的互斥访问共享资源,通过一个线程获得对共享资源的独占访问权限,其他线程必须等待互斥访问结束才能访问。
  3. 使用方式:

    • 同步机制可以通过各种机制来实现,如信号量、条件变量、屏障等。它通常涉及线程之间的通信、等待和唤醒操作,以及协调线程之间的执行顺序和同步。
    • 互斥机制可以通过锁(比如互斥锁、读写锁)来实现。它通常涉及到线程之间的互斥操作,即一个线程获得锁后,其他线程就必须等待,直到当前线程释放锁。
  4. 应用场景:

    • 同步机制常用于需要协调线程之间的操作顺序、共享数据访问和条件等待的场景,如生产者消费者问题、多线程并发任务的协调执行等。
    • 互斥机制常用于保护共享资源的访问,防止多线程之间出现数据竞争和不一致性的场景,如对共享变量的访问、文件的读写等。

需要注意的是,同步和互斥并不是互斥的概念,它们经常同时使用来保证数据的一致性和共享资源的安全访问。在实际应用中,可以使用同步机制来确保线程之间的协调和有序执行,并使用互斥机制来保护共享资源的访问。

3.4 并发相关的基本概念

  • 1.原子操作:一个函数(原语)或动作的指令序列不可分割,要么作为一个整体执行(不可中断),要么都不执行

  • 2.临界资源:一次仅允许一个进程独占使用的不可剥夺的资源

  • 3.临界区:进程访问临界资源的那段程序代码。一次仅允许一个进程在临界区中执行

  • 4.互斥:当一个进程正在临界区中访问临界资源时,其他进程不能进入临界区

  • 5.同步:合作的并发进程需要按先后次序执行,例如:一个进程的执行依赖于合作进程的消息或者信号,当一个进程没有得到来自于合作进程的消息或者信号时需要阻塞等待,直到消息或者信号到达后才被唤醒

  • 6.死锁:多个进程全部阻塞,形成等待资源的循环链

  • 7.饥饿:一个就绪进程被调度程序长期忽视、不被调度执行;一个进程长期得不到资源

3.5 PV操作

PV操作是一种实现进程互斥与同步的有效方法,是原子操作!

PV操作与信号量的处理相关,P表示通过的意思,V表示释放的意思。

PV操作是典型的同步机制之一。

用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;

当信号量的值非0时,表示期望的消息已经存在。

用PV操作实现进程同步时,调用P操作测试消息是否到达,调用V操作发送消息。

上述有两个信号量:

一个用于写同步,必须有空闲缓冲区才能写,用于检查缓冲是否满,如果满,则等待,如果不满,则写。

一个用于读同步,缓冲区中必须有数据才能读,用于检查缓冲区是否空,如果空,则等待,如果不空,则读。

为什么需要两个信号量呢???

单一的信号量只能做到互斥,无法实现读、写同步,必须有空闲缓冲区才能写,冲区中必须有数据才能读的功效!!!即一个信号量用于检查缓冲区是否空,一个用于检查缓冲区是否满。

PV操作的本质是:改变线程的状态,或者说触发线程状态的切合。

P操作本质是把进程的执行态转换到阻塞状态。

V操作的本质是进程的阻塞状态变成就绪态。

3.6 进程的死锁

3.6.1 定义

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 [1]

死锁的规范定义:集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。

一种情形,此时执行程序中两个或多个进程发生永久堵塞(等待),每个进程都在等待被其他进程占用并堵塞了的资源。例如,如果进程A锁住了记录1并等待记录2,而进程B锁住了记录2并等待记录1,这样两个进程就发生了死锁现象。

计算机系统中,如果系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。

在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此时会造成这些任务永久阻塞,从而出现死锁。例如:事务A 获取了行 1 的共享锁。事务 B 获取了行 2 的共享锁。

3.6.2 产生条件

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。 [2]

1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件:指进程已经保持至少一个资源,又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放

3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

所谓打破死锁:就是调度进程已经发现死锁,如何打破现有的死锁。

所谓预防死锁:就是死锁发生前,在设计就避免死锁的算法。

3.6.3 有序资源分配法

在每个线程所需要资源数量都减1的情况下,在增加一个资源,就能够有效的避免死锁。

3.6.4 银行算法

银行家算法(Banker's Algorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。

在银行中,客户申请贷款的数量是有限的,每个客户在第一次申请贷款时要声明完成该项目所需的最大资金量,在满足所有贷款要求时,客户应及时归还。银行家在客户申请的贷款数量不超过自己拥有的最大值时,都应尽量满足客户的需要。

在这样的描述中,银行家就好比操作系统,资金就是资源,客户就相当于要申请资源的进程。

银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。为实现银行家算法,系统必须设置若干数据结构

要解释银行家算法,必须先解释操作系统安全状态和不安全状态。

安全序列是指一个进程序列{P1,…,Pn}是安全的,即对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。

安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。安全状态一定是没有死锁发生。

不安全状态:不存在一个安全序列。不安全状态不一定导致死锁

有新进程申请资源时,调度程序首先确保,分配后的剩余的资源能够保证已经申请资源的进程能够安全执行,不发生死锁,只有剩余资源能够保证所有进程不发生死锁时才会为新进程分配资源,否则暂缓分配资源。

补充材料:

原子操作变量和普通变量

原子操作变量和普通变量在并发编程中有以下区别和比较:

  1. 原子性:原子操作变量具有原子性,即对于原子操作变量的读取和写入操作是不可中断的。而普通变量的操作不具备原子性,可能会在多线程环境中导致数据竞争和不一致性的问题。

  2. 线程安全性:原子操作变量是线程安全的,可以在多个线程之间并发地访问而无需额外的同步机制。因为原子操作变量的读取和写入操作是原子的,不会出现线程间的数据竞争和不一致性。普通变量不具备线程安全性,需要使用同步机制(如互斥锁、条件变量等)来保证线程安全性。

  3. 内存可见性:原子操作变量可以确保多个线程对其值的修改和读取在不同线程之间都是可见的。这是因为原子操作的实现通常使用了内存屏障或者锁来保证可见性。普通变量在没有同步机制的情况下,可能存在线程间的内存不一致性问题。

  4. 性能开销:原子操作变量相对于普通变量可能会存在一定的性能开销。由于原子操作需要保证原子性和线程安全性,通常会使用底层的原子指令或锁机制,这可能会引入额外的开销。而普通变量在不需要考虑线程间同步的情况下,没有这些开销。

需要综合考量实际的并发需求来选择使用原子操作变量还是普通变量。如果多个线程之间需要并发访问共享变量,并且要求原子性和线程安全性,可以选择使用原子操作变量。而对于单线程或者不需要考虑并发的情况下,普通变量可能更为简单和高效。

总结来说,原子操作变量提供了一种方便且线程安全的方式来处理并发访问共享变量的需求,可以避免线程间的数据竞争和不一致性。普通变量则更适用于单线程或者简单的非并发场景,不需要考虑线程安全性和原子性。

原子操作变量的原理

原子操作变量的原理可以从硬件和软件两个层面进行解释。

在硬件层面,原子操作变量的原理通常依赖于处理器的原子指令(Atomic Instruction),这些指令是由处理器提供的特殊指令,可以保证某些操作的原子性。原子指令使用底层的硬件机制来确保操作的原子性,通常涉及处理器引入的内存屏障(memory barrier)和总线锁定(bus locking)。通过这些机制,原子操作的读取和写入能够在多线程或多进程环境中实现原子性

在软件层面,原子操作变量的原理通常依赖于同步机制的实现。这些同步机制可以是基于硬件的原子指令,也可以是基于软件的算法和数据结构。常见的软件实现方式包括使用互斥锁(mutex)、条件变量、屏障(barrier)等。通过使用这些同步机制,原子操作变量可以实现对共享资源的访问的互斥和同步。

具体到原子操作的实现,一些编程语言提供了原子类型(如原子整数、原子指针等),它们通过底层的原子指令或锁机制来保证原子操作的原子性。原子类型提供了一些常见的操作(如读取、写入、增加、减少等),这些操作会在底层进行同步和原子操作,保证多线程或多进程的并发访问安全和一致。

总结来说,原子操作变量的原理基于硬件和软件层面的支持。在硬件层面,原子指令和底层的硬件机制确保了原子操作的原子性。在软件层面,使用同步机制(如互斥锁、条件变量等)实现了对共享资源的互斥和同步。通过这些机制,原子操作变量能够在多线程或多进程环境中保证操作的原子性、线程安全性和内存可见性。

为什么说普通变量的访问不具备原子性

普通变量的访问不具备原子性的主要原因是其操作不是不可中断的

在多线程或多进程环境中,当多个线程或进程同时对同一个普通变量进行读取或写入操作时,可能会产生竞态条件(Race Condition)。

竞态条件指的是对共享资源的访问顺序不确定,导致最终结果的不一致性。

举个例子,假设有两个线程同时对一个普通变量进行自增操作:
Thread 1: x = x + 1;
Thread 2: x = x + 1;
在单独执行每条语句时,看起来每个线程对变量 x 进行自增操作是原子的。然而,在并发情况下,当 Thread 1 和 Thread 2 同时读取 x 并进行自增操作时,可能会发生以下情况:

  1. Thread 1 读取 x 的值为 1,
  2. Thread 2 读取 x 的值也为 1, //Thread 1对x的读操作被Thread 2对x的读操作打断,线程对x的读操作不具备原子性
  3. Thread 1 和 Thread 2 都将 x 增加 1,
  4. 最终结果 x 的值为 2,而不是期望的 3。

这是因为普通变量的读取和写入操作通常不是一条原子指令,它们可能被中断,并发执行的线程可能会交错执行,导致不确定性和竞态条件

为了避免这种问题,需要采取适当的同步机制(如互斥锁、原子操作变量等原子操作的变量进行包含),保证多个线程对普通变量的访问和修改是原子的,从而避免数据竞争和不一致性。使用原子操作变量可以在并发环境中实现原子性操作,而不需要额外的同步机制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文火冰糖的硅基工坊

你的鼓励是我前进的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值