技术周总结 10.14-10.20 周日(软考大系(系统架构师))

一、10.16 周三

1.1)问题01: java 中,final String aaa 和 String aaa的区别?

在 Java 中,final String aaaString aaa 之间的主要区别在于使用了 final 关键字。final 关键字的作用是使得变量一旦被赋值之后就不能再被修改。下面详细解释这两者的区别:

1. String aaa

String aaa = "Hello";
  • 可变性aaa 是一个普通的字符串变量,可以在其生命周期内被重新赋值。

  • 示例

    String aaa = "Hello";
    aaa = "World";  // 重新赋值是允许的
    

2. final String aaa

final String aaa = "Hello";
  • 不可变性:使用 final 关键字修饰的字符串变量一旦被赋值之后,就不能再被重新赋值。

  • 示例

    final String aaa = "Hello";
    aaa = "World";  // 编译错误,不能重新赋值
    

详细解释

  1. 存储位置

    • String aaa:存储在堆内存中的字符串常量池中。可以被重新赋值。
    • final String aaa:同样存储在堆内存中的字符串常量池中,但由于 final 修饰,引用被固定,不能重新指向其他字符串对象。
  2. 编译时常量

    • final String aaa:如果 aaa 是一个编译时常量(即在编译时就能确定其值),那么它可以在编译过程中进行内联优化。例如:

      final String aaa = "Hello";
      final String bbb = aaa + " World";
      System.out.println(bbb);  // 输出 "Hello World"
      

      在这种情况下,编译器会在编译时期将 bbb 的值计算为 "Hello World"

      扫描二维码关注公众号,回复: 17409315 查看本文章
  3. 线程安全

    • final String aaa:由于 final 关键字确保了变量在初始化之后不会再被修改,因此在多线程环境中是线程安全的。

示例代码

以下是一个简单的示例代码,展示了 final String 和普通 String 的区别:

public class FinalStringExample {
    
    
    public static void main(String[] args) {
    
    
        // 普通字符串变量
        String str1 = "Hello";
        str1 = "World";  // 允许重新赋值

        // final 字符串变量
        final String str2 = "Hello";
        // str2 = "World";  // 编译错误,不允许重新赋值

        System.out.println("str1: " + str1);  // 输出 "str1: World"
        System.out.println("str2: " + str2);  // 输出 "str2: Hello"
    }
}

总结

  • String aaa:普通字符串变量,可以被重新赋值。
  • final String aaa:用 final 修饰的字符串变量,一旦赋值后就不能再被修改,这使得它在某些场景下(如常量、线程安全)更有用。

1.2)问题02:C#中 string.Empty和 ""的区别是什么?

在C#中,string.Empty""(空字符串)在功能上实际上是等价的,但它们有一些细微的差别:

  1. 语义上的区别

    • string.Empty是一个静态字段,表示一个空字符串。它更具有语义性,明确表示这是一个空的字符串。
    • ""是一个字面量,表示一个空字符串。
  2. 性能上的区别

    • 在性能上,两者几乎没有区别。编译器在编译时对""做了优化,通常会将其替换为string.Empty
  3. 可读性和意图

    • 使用string.Empty可以更清楚地表达程序员的意图,即你希望使用一个空的字符串。
    • 使用""则可能更简洁,但在某些情况下可能不如string.Empty明显。

以下是一个简单的代码示例:

string str1 = string.Empty;
string str2 = "";

这两行代码定义的字符串变量str1str2在内容上是相同的,都是空字符串。

总结:

  • 如果你希望代码更具可读性和意图明确,可以使用string.Empty
  • 如果你更喜欢简洁的代码,可以使用""

二、10.18 周五

2.1)问题01: 数据库事务

数据库事务是数据库管理系统执行过程中的一个逻辑单位,它由一系列对系统中数据进行管理(如读取和更新)的操作组成。事务具有ACID属性,即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这些特性确保了事务处理的可靠性和正确性。

原子性(Atomicity)

事务必须是一个不可分割的工作单元,这意味着事务中的所有操作要么全部完成,要么完全不执行。如果事务的一部分失败,那么整个事务将被回滚,恢复到事务开始前的状态。

一致性(Consistency)

事务执行前后,数据库必须保持一致状态。这包括满足所有的预定义约束、触发器和级联等规则。事务不应破坏数据库的一致性。

隔离性(Isolation)

事务的执行应该是独立的,不受其他事务的影响。这意味着在并发环境下,每个事务看起来都是顺序执行的,即使它们实际上是并行运行的。通过适当的锁机制或版本控制,可以实现这一特性。

持久性(Durability)

一旦事务提交,其结果就是永久性的,即使系统发生故障也不会改变。这意味着事务的结果必须被写入持久化存储中。

数据库事务的常见类型

  • 读取事务:从数据库中读取数据而不进行修改。
  • 写入事务:向数据库中插入新记录或更新现有记录。
  • 删除事务:从数据库中移除记录。
  • 复合事务:包含多个操作,可能涉及读取、写入和删除等。

实现事务的方法

数据库管理系统通常提供SQL语句来支持事务处理,例如:

  • BEGIN TRANSACTIONSTART TRANSACTION:开始一个新的事务。
  • COMMIT:提交当前事务,使所有更改成为永久性的。
  • ROLLBACK:撤销当前事务中所有未提交的操作。

并发控制

为了保证事务的隔离性,数据库管理系统使用各种并发控制技术,比如锁机制、乐观锁和悲观锁、多版本并发控制(MVCC)等。

理解事务的概念及其重要性对于开发可靠的应用程序至关重要,特别是在需要处理大量并发操作的场景下。正确的事务管理可以防止数据丢失、数据损坏和其他潜在的问题。

2.2) 详细展开数据库事务的持久性

数据库事务的持久性(Durability)是指一旦事务成功提交,其对数据库所做的所有更改都将永久保存,即使是在系统崩溃或遇到其他异常情况之后也是如此。这是事务四个ACID属性之一,确保了数据的一致性和可靠性。下面详细解释持久性的几个方面:

1. 日志记录(Logging)

为了实现持久性,大多数数据库管理系统会使用日志记录技术。当事务提交时,数据库不仅会将数据更改应用到主存储区,还会将这些更改的信息写入一个称为“重做日志”(Redo Log)或“事务日志”(Transaction Log)的文件中。这个日志文件记录了事务的所有操作,包括数据的修改前后的状态。

日志的作用:
  • 恢复:如果系统崩溃后重启,数据库可以通过重放日志中的记录来恢复未完成的事务,确保已提交的事务不会丢失。
  • 回滚:如果事务需要回滚,日志也可以帮助撤销已经做出的更改。

2. 写前日志(Write-Ahead Logging, WAL)

写前日志是一种常见的日志策略,要求在任何数据更改写入磁盘之前,相关的日志记录必须先写入磁盘。这样可以确保即使系统在数据写入过程中崩溃,日志记录仍然存在,可以用于恢复。

3. 两阶段提交(Two-Phase Commit, 2PC)

在分布式系统中,事务可能涉及多个节点。为了确保所有节点上的更改都能持久化,通常会使用两阶段提交协议。该协议分为两个阶段:

  • 准备阶段:协调者询问所有参与者是否准备好提交事务。如果所有参与者都回复“是”,则进入第二阶段。
  • 提交阶段:协调者发送提交请求给所有参与者,每个参与者将更改写入磁盘并确认提交。

4. 检查点(Checkpoint)

检查点是数据库系统定期创建的一种机制,用于减少恢复时间。检查点记录了数据库的一个稳定状态,包括所有已提交事务的日志位置。在系统恢复时,可以从最近的检查点开始重放日志,而不是从头开始。

5. 缓存与刷新(Buffering and Flushing)

数据库系统通常会使用缓存来提高性能。在事务提交时,更改首先写入内存中的缓冲区,然后异步地刷新到磁盘。为了确保持久性,数据库系统会确保在事务提交之前,相关的日志记录已经被写入磁盘,并且在适当的时候将缓冲区的数据刷新到磁盘。

6. 故障恢复

在系统发生故障后,数据库管理系统会自动启动恢复过程。恢复过程通常包括以下几个步骤:

  • 重做(Redo):根据日志记录重新执行已提交事务的更改。
  • 撤销(Undo):撤销未提交事务的更改。

示例

假设有一个简单的银行转账事务,从账户A转100元到账户B。以下是事务处理流程:

  1. 开始事务BEGIN TRANSACTION
  2. 扣款:从账户A扣除100元。
  3. 存款:向账户B增加100元。
  4. 写日志:将上述操作记录到事务日志中。
  5. 提交事务COMMIT

在这个过程中,数据库会确保所有更改都被记录到日志中,并且在事务提交之前,日志记录已经被写入磁盘。即使在事务提交后系统崩溃,数据库在重启时也可以通过重放日志来恢复这笔转账操作。

总结

持久性是数据库事务的重要属性,确保了数据的一致性和可靠性。通过日志记录、写前日志、两阶段提交、检查点和缓存刷新等技术,数据库管理系统能够有效地实现持久性,即使在系统故障的情况下也能保证已提交事务的效果。

三、10.20 周日

3.1)问题01:计算机组成原理:磁盘管理

磁盘管理是计算机存储系统中的重要组成部分,涉及到如何高效地管理和使用磁盘存储设备。以下是磁盘管理的一些关键概念和技术,涵盖了磁盘结构、寻址方式、调度算法等。

1. 磁盘的基本结构

  • 盘片(Platter):磁盘内部由多个圆形的盘片组成,这些盘片具有磁性涂层,用来存储数据。每个盘片的两个表面都可以用来存储数据。
  • 磁道(Track):盘片的表面被划分为同心圆环,称为磁道。每个盘片的表面包含若干个磁道。
  • 扇区(Sector):磁道被进一步划分为多个扇区,扇区是磁盘数据存储的基本单位。常见的扇区大小是 512 字节或 4KB。
  • 柱面(Cylinder):所有盘片中位于相同半径上的磁道组成一个柱面。数据的访问可以通过柱面方式实现,因为同一个柱面上,磁头不需要移动即可访问不同盘片的相应位置。

2. 磁盘寻址

  • CHS(Cylinder-Head-Sector)寻址
    • 早期的磁盘采用 柱面-磁头-扇区(Cylinder-Head-Sector, CHS) 模式来确定数据的位置。需要指定磁盘的柱面号、磁头号和扇区号来访问数据。
    • 这种方式随着磁盘容量的增大已经不常用,更多的被逻辑块寻址(LBA)替代。
  • LBA(Logical Block Addressing)寻址
    • LBA 是现在磁盘常用的寻址方式,它将整个磁盘上的扇区按顺序编号,用一个逻辑块地址来表示一个扇区位置。这种方式摆脱了物理结构的限制,简化了磁盘管理和寻址。

3. 磁盘调度算法

磁盘调度是指操作系统调度磁盘读写请求的方式,目的是减少磁盘访问延迟,提高系统性能。常见的调度算法有:

  • 先来先服务(FCFS, First Come First Serve)

    • 磁盘按照请求的到达顺序进行处理,不考虑磁头的当前位置或移动距离。
    • 优点:实现简单。
    • 缺点:磁头可能会频繁在盘面上大幅度移动,导致性能下降。
  • 最短寻道优先(SSTF, Shortest Seek Time First)

    • 每次选择离当前磁头位置最近的请求进行处理,减少磁头移动的距离。
    • 优点:减少磁头移动的平均距离和时间。
    • 缺点:可能会出现 饥饿现象,即某些距离较远的请求长时间得不到处理。
  • 扫描算法(SCAN)

    • 磁头在盘面上不断地从一端扫描到另一端,处理途中遇到的所有请求。到达另一端后,磁头方向反向,继续处理请求。
    • 优点:可以避免 SSTF 的饥饿问题,磁头移动有规律,效率较高。
    • 缺点:远端的请求可能要等待较长时间。
  • 循环扫描(C-SCAN)

    • 类似于 SCAN,但当磁头到达一端后直接回到另一端的起始位置,而不处理中途的请求。这确保了每个请求的等待时间相对一致。
    • 优点:避免了 SCAN 算法中,远端请求等待较长时间的情况,平均等待时间更一致。
    • 缺点:每次扫描的磁头回程没有处理请求,可能造成磁头的非必要移动。
  • LOOK 和 C-LOOK

    • 这是 SCAN 和 C-SCAN 的优化版本,磁头不必移动到盘面的边缘,而是只在请求所在范围内移动。当到达最后一个请求时,磁头即反向(LOOK)或返回起始点(C-LOOK)。
    • 优点:进一步减少磁头的移动距离。

4. 磁盘格式化与文件系统

  • 低级格式化:也称为物理格式化,负责将磁盘划分为多个扇区并确定数据存储的物理结构。这一步会建立扇区、磁道等基本结构。
  • 高级格式化:通常是指安装文件系统的过程。操作系统通过文件系统将磁盘逻辑化,将磁盘空间划分为文件和文件夹等结构,便于管理。

5. 磁盘缓存与缓存管理

磁盘缓存是内存中的一部分,用来暂时存储磁盘数据,以减少物理磁盘访问的次数,提升性能。磁盘缓存常用的管理策略包括:

  • LRU(Least Recently Used):将最久未使用的数据从缓存中移除。
  • LFU(Least Frequently Used):将使用频率最低的数据从缓存中移除。
  • 预读策略:在处理当前读请求时,将相邻的数据块预先读取到缓存中,以应对接下来的连续读操作,提高访问速度。

6. 磁盘分区

磁盘可以被分为多个逻辑部分,即磁盘分区。每个分区可以独立使用,安装不同的文件系统,或用于不同的用途。常见的分区类型有:

  • 主分区(Primary Partition):通常是用来启动操作系统的分区。每个磁盘最多可以有 4 个主分区。
  • 扩展分区(Extended Partition):如果需要创建超过 4 个分区,则可以创建扩展分区,扩展分区可以包含多个逻辑分区。
  • 逻辑分区(Logical Partition):位于扩展分区中的分区,通常用于存储非操作系统数据。

7. RAID(Redundant Array of Independent Disks)

RAID 是通过组合多个物理磁盘,来提高数据存储的可靠性性能。不同级别的 RAID 提供不同的冗余和性能特性:

  • RAID 0:将数据条带化分布到多个磁盘上,提供高性能,但无冗余,数据丢失风险高。
  • RAID 1:将数据镜像到多个磁盘,提供高数据冗余,但存储效率较低。
  • RAID 5:使用分布式奇偶校验,既有数据冗余,又提供较好的存储效率。
  • RAID 6:类似于 RAID 5,但有双重奇偶校验,可以容忍两个磁盘同时故障。
  • RAID 10:结合 RAID 0 和 RAID 1,提供高性能和高冗余。

总结:

磁盘管理在计算机组成和操作系统设计中非常重要。它通过各种调度算法、寻址方式、缓存管理等技术,最大化磁盘的性能,并保证数据的完整性和安全性。

在这里插入图片描述

这是一张显示磁盘基本结构的示意图。图中展示了多个堆叠在主轴上的盘片(Platter),每个盘片有同心的磁道(Track),磁道被进一步划分为扇区(Sector)。读写头(Read/Write Head)悬停在一个盘片上,用于执行读写操作,示意图中也展示了柱面(Cylinder)的概念,将所有盘片上的同心磁道对齐。

猜你喜欢

转载自blog.csdn.net/xinkuaile/article/details/142988668