【C# 数据结构】队列 FIFO

目录

  • 队列的概念
  • FIFO (First-In, First-Out)
      • `Queue<T>` 的工作原理:
      • 示例:
        • 解释:
      • 小结:
  • 环形队列
      • 1. **FIFO?**
      • 2. **环形缓冲队列如何实现FIFO?**
        • 关键概念:
      • 3. **环形缓冲队列的工作过程**
        • 假设:
        • 操作步骤:
      • 4. **具体例子**
        • 初始状态:
        • 操作1:入队数据 `A`
        • 操作2:入队数据 `B`
        • 操作3:出队
        • 操作4:入队数据 `C`, `D`, `E`
        • 操作5:出队
        • 操作6:入队数据 `F`
        • 操作7:出队
      • 5. **环形缓冲队列的FIFO特性**
      • 6. **环形缓冲队列的FIFO优势**
      • 7. **小结**
  • C# 如何通过代码实现环状队列?
      • 1. **使用 `Queue<T>` 实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 2. **使用固定大小数组实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 小结
  • 队列和环状队列的对比
      • 1. **环形缓冲队列是FIFO的一种实现**
      • 2. **环形缓冲队列的特点**
      • 3. **环形缓冲队列 vs 其他FIFO实现**
      • 4. **环形缓冲队列的局限性**
      • 5. **小结**
  • 线程安全问题
      • Queue<T> 如果一个线程只负责写,一个线程只负责读会有问题吗?
      • 问题原因:
      • 一些潜在的风险:
      • 如何解决?
        • 1. 使用锁 (`lock`)
        • 2. 使用 `ConcurrentQueue<T>`
      • 总结:

队列的概念

队列和FIFO是什么关系?队列是一种数据结构。
FIFO是队列需要遵循的基本原则:First-In, First-Out。或者说FIFO是队列的基本特性!
C#中有个类叫做Queue,就是实现了队列这种数据结构的类,它遵循FIFO这个原则。

FIFO (First-In, First-Out)

FIFO(First In First Out,先进先出)是一种数据管理原则,就像排队一样:

  • 先进入队列的数据先被处理
  • 后进入队列的数据后被处理

在 FIFO 队列中,第一个进入队列的元素将是第一个被移除的元素。换句话说,队列中的元素按照它们被加入的顺序排列,最早加入的元素最先被取出。

Queue<T> 的工作原理:

  • 入队 (Enqueue):新元素被添加到队列的尾部。
  • 出队 (Dequeue):最早加入队列的元素从队列的头部移除,并返回该元素。

示例:

假设我们使用一个容量为 3 的队列,依次加入元素 123,然后进行 Dequeue() 操作:

Queue<int> queue = new Queue<int>();

// 入队操作
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);

// 出队操作,按照 FIFO 顺序返回
Console.WriteLine(queue.Dequeue()); // 输出 1
Console.WriteLine(queue.Dequeue()); // 输出 2
Console.WriteLine(queue.Dequeue()); // 输出 3
解释:
  • Enqueue(1)1 加入队列的尾部。
  • Enqueue(2)2 加入队列的尾部。
  • Enqueue(3)3 加入队列的尾部。
  • Dequeue() 返回并移除队列的头部元素,即最早加入的 1,然后是 23,遵循 FIFO 的顺序。

小结:

通过Queue<T> 的使用我们可以很好的理解 FIFO ,其中元素按照加入的顺序进行排队,最早加入的元素最先被取出。这使得它特别适用于处理排队和任务调度等场景。

环形队列


1. FIFO?

环状队列也是队列的一种,当然也遵循FIFO这个原则!

2. 环形缓冲队列如何实现FIFO?

环形缓冲队列是一种用固定大小的数组实现FIFO的方式。它通过两个指针(头指针和尾指针)来管理数据的入队和出队。

关键概念:
  • 固定大小的数组:预分配一块连续的内存空间。
  • 头指针(head):指向下一个数据写入的位置。
  • 尾指针(tail):指向下一个数据读取的位置。
  • 循环利用:当指针到达数组末尾时,会回到数组开头,形成一个“环”。

3. 环形缓冲队列的工作过程

让我们通过一个具体的例子来说明。

假设:
  • 环形缓冲队列的容量为 5(即数组大小为5)。
  • 初始状态:队列为空,headtail 都指向位置 0
操作步骤:
  1. 入队(Enqueue)

    • 将数据写入 head 指向的位置。
    • 然后 head 向前移动一位。
    • 如果 head 到达数组末尾,它会回到数组开头(循环特性)。
  2. 出队(Dequeue)

    • tail 指向的位置读取数据。
    • 然后 tail 向前移动一位。
    • 如果 tail 到达数组末尾,它会回到数组开头。

4. 具体例子

初始状态:
数组索引: [0]  [1]  [2]  [3]  [4]
值:      None None None None None
head = 0, tail = 0
操作1:入队数据 A
  • A 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A    None None None None
head = 1, tail = 0
操作2:入队数据 B
  • B 写入 head 指向的位置(索引 1)。
  • head 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 0
操作3:出队
  • tail 指向的位置(索引 0)读取数据 A
  • tail 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 1
操作4:入队数据 C, D, E
  • 依次将 C, D, E 写入 head 指向的位置。
  • head 移动到下一个位置。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 1
操作5:出队
  • tail 指向的位置(索引 1)读取数据 B
  • tail 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 2
操作6:入队数据 F
  • F 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 2
操作7:出队
  • tail 指向的位置(索引 2)读取数据 C
  • tail 移动到下一个位置(索引 3)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 3

5. 环形缓冲队列的FIFO特性

  • 数据顺序:先入队的数据(如 A, B)先出队,后入队的数据(如 C, D, E)后出队。
  • 循环利用:当 headtail 到达数组末尾时,会回到数组开头,继续使用之前释放的空间。
  • 固定容量:队列的大小是固定的,当队列满时,可以选择覆盖旧数据或报错。

6. 环形缓冲队列的FIFO优势

  • 高效:入队和出队操作的时间复杂度都是 O(1)。
  • 内存紧凑:数据连续存储,缓存友好。
  • 适合实时系统:适合处理固定大小的数据流。

7. 小结

  • 环形缓冲队列是FIFO的一种实现,它通过固定大小的数组和循环指针来实现先进先出的特性。
  • 数据按顺序入队和出队,先进入队列的数据先被处理。
  • 循环利用使得内存使用更高效,适合处理固定大小的数据流。
    通过理解环状队列你是不是对队列又有了更深的理解呢? 😊

C# 如何通过代码实现环状队列?

之前说到,C# 中有个现成的类实现了队列就是Queue这个类。但是并没有现成的环状队列。

要手动实现环形缓冲队列(Circular Buffer)在 C# 中,可以通过结合 Queue<T> 或者直接使用一个固定大小的数组来模拟环形队列的行为。下面是两种常见的实现方式。

1. 使用 Queue<T> 实现环形缓冲队列

虽然 Queue<T> 本身并不是环形队列,但我们可以通过管理队列的最大容量和覆盖旧数据来模拟环形缓冲队列的行为。当队列满时,新的数据会覆盖最旧的数据。

public class CircularQueue<T>
{
    private readonly Queue<T> queue;
    private readonly int capacity;

    public CircularQueue(int capacity)
    {
        this.capacity = capacity;
        this.queue = new Queue<T>(capacity);
    }

    // 添加元素,如果队列已满,则移除最旧的元素
    public void Enqueue(T item)
    {
        if (queue.Count == capacity)
        {
            queue.Dequeue(); // 移除最旧的元素
        }
        queue.Enqueue(item);
    }

    // 从队列中取出元素
    public T Dequeue()
    {
        if (queue.Count == 0)
        {
            throw new InvalidOperationException("Queue is empty.");
        }
        return queue.Dequeue();
    }

    // 查看队列中的第一个元素
    public T Peek()
    {
        if (queue.Count == 0)
        {
            throw new InvalidOperationException("Queue is empty.");
        }
        return queue.Peek();
    }

    // 判断队列是否为空
    public bool IsEmpty() => queue.Count == 0;

    // 队列中的元素个数
    public int Count => queue.Count;
}

使用示例:

CircularQueue<int> circularQueue = new CircularQueue<int>(3);

circularQueue.Enqueue(1);
circularQueue.Enqueue(2);
circularQueue.Enqueue(3);

Console.WriteLine(circularQueue.Dequeue()); // 输出 1
circularQueue.Enqueue(4); // 现在队列已满,1 会被覆盖

Console.WriteLine(circularQueue.Dequeue()); // 输出 2
Console.WriteLine(circularQueue.Dequeue()); // 输出 3
Console.WriteLine(circularQueue.Dequeue()); // 输出 4

说明:

  • Queue<T> 用于存储数据,最大容量为 capacity
  • 当队列满时(元素数量等于 capacity),通过 Dequeue() 移除最旧的元素,再插入新的元素,模拟环形缓冲的行为。

这种方式依赖于 Queue<T> 来管理队列的基本操作,简单易懂,但不能完全利用环形缓冲队列的内存高效性,尤其是在每次扩展队列容量时仍会引起内存分配。


2. 使用固定大小数组实现环形缓冲队列

这种方法通过手动管理队列的头尾指针和数组来实现环形缓冲区,避免了 Queue<T> 的扩展和额外的内存分配。下面是一个更低层次的实现方式:

public class CircularBuffer<T>
{
    private readonly T[] buffer;
    private int head;
    private int tail;
    private int size;
    private readonly int capacity;

    public CircularBuffer(int capacity)
    {
        this.capacity = capacity;
        this.buffer = new T[capacity];
        this.head = 0;
        this.tail = 0;
        this.size = 0;
    }

    // 添加元素到队列
    public void Enqueue(T item)
    {
        if (size == capacity)
        {
            // 队列已满,覆盖最旧的数据
            head = (head + 1) % capacity; // 更新头指针
        }
        else
        {
            size++;
        }
        
        buffer[tail] = item;
        tail = (tail + 1) % capacity; // 更新尾指针
    }

    // 从队列中取出元素
    public T Dequeue()
    {
        if (size == 0)
        {
            throw new InvalidOperationException("Queue is empty.");
        }

        T value = buffer[head];
        head = (head + 1) % capacity; // 更新头指针
        size--;
        return value;
    }

    // 查看队列的第一个元素
    public T Peek()
    {
        if (size == 0)
        {
            throw new InvalidOperationException("Queue is empty.");
        }

        return buffer[head];
    }

    // 判断队列是否为空
    public bool IsEmpty() => size == 0;

    // 队列中的元素个数
    public int Count => size;
}

使用示例:

CircularBuffer<int> buffer = new CircularBuffer<int>(3);

buffer.Enqueue(1);
buffer.Enqueue(2);
buffer.Enqueue(3);

Console.WriteLine(buffer.Dequeue()); // 输出 1
buffer.Enqueue(4); // 1 被覆盖

Console.WriteLine(buffer.Dequeue()); // 输出 2
Console.WriteLine(buffer.Dequeue()); // 输出 3
Console.WriteLine(buffer.Dequeue()); // 输出 4

说明:

  • 通过一个固定大小的数组 buffer 存储数据,队列大小为 capacity
  • headtail 指针管理数据的入队和出队。head 指针指向队列的头部(最旧的元素),tail 指针指向队列的尾部(最新的元素)。
  • 当队列满时,新元素会覆盖最旧的数据,head 指针会移动到下一个位置,从而实现环形缓冲队列的覆盖行为。

这种方式比 Queue<T> 更高效,避免了额外的内存分配,适合需要频繁进行入队和出队操作的场景。


小结

  • 使用 Queue<T>:可以通过在队列满时删除最旧元素来模拟环形缓冲队列,适用于简单的场景。
  • 使用固定大小数组:手动管理头尾指针和队列大小,更高效,避免内存分配,适用于性能要求较高的场景。

队列和环状队列的对比


1. 环形缓冲队列是FIFO的一种实现

  • FIFO原则:数据按照到达顺序处理,先进入队列的数据先被取出。
  • 环形缓冲队列:通过固定大小的数组和循环指针实现FIFO,满足先进先出的特性。

2. 环形缓冲队列的特点

  • 固定大小:预分配固定容量的内存,空间利用率高。
  • 循环利用:通过头尾指针循环移动,重复利用数组空间。
  • 高效性能:插入和删除操作的时间复杂度都是O(1)。
  • 内存紧凑:数据连续存储,缓存友好。

3. 环形缓冲队列 vs 其他FIFO实现

特性环形缓冲队列链表实现的FIFO动态数组实现的FIFO
内存分配一次性预分配动态分配节点动态扩容
空间利用率100%较低(每个节点有额外开销)较高(但有扩容开销)
插入/删除性能O(1)O(1)均摊O(1),扩容时O(n)
随机访问不支持不支持支持
适用场景固定大小数据流、实时系统数据量变化大、简单实现需要随机访问的场景

4. 环形缓冲队列的局限性

  • 固定大小:需要预先确定容量,不适合数据量变化大的场景。
  • 不支持随机访问:只能按顺序访问数据。
  • 溢出处理:队列满时需要明确策略(覆盖旧数据或报错)。

5. 小结

  • 环形缓冲队列是FIFO的一种高效实现,特别适合固定大小、高吞吐量的场景。
  • 它通过循环利用预分配的内存,避免了动态内存分配的开销,同时保持了FIFO的特性。
  • 如果需要动态扩容或更灵活的内存管理,可以选择其他FIFO实现(如链表或动态数组)。

线程安全问题


1 多线程访问队列的潜在问题
1.1 竞态条件(Race Condition)
问题描述:多个线程同时修改队列的状态(如 head 和 tail 指针),导致数据不一致。

示例:
线程A和线程B同时执行入队操作。
两者读取相同的 head 指针值,导致数据覆盖或丢失。

1.2 数据不一致
问题描述:一个线程正在修改队列,另一个线程同时读取队列,导致读取到不完整或错误的数据。

示例:

线程A正在入队,更新了 head 指针但还未写入数据。

线程B读取 head 指针,误认为新数据已写入。

1.3 死锁(Deadlock)
问题描述:多个线程互相等待对方释放锁,导致程序无法继续执行。

示例:

线程A持有锁1并等待锁2。

线程B持有锁2并等待锁1。

Queue 如果一个线程只负责写,一个线程只负责读会有问题吗?

如果一个线程 只负责写Enqueue)而另一个线程 只负责读Dequeue),在 不使用锁 或其他线程同步机制的情况下,Queue<T> 仍然 可能会遇到问题,即使你不打算在同一时间内进行读写操作。

问题原因:

  • 队列的内部状态Queue<T> 并没有内建的线程安全机制来保证即使在读写操作不重叠的情况下,两个线程对队列的访问是安全的。
    • 例如,读线程可能会在 写线程 操作队列时,导致内部数据不一致或访问冲突。即使一个线程只负责写,另一个线程只负责读,也可能会出现 竞态条件(race condition)或 内存可见性问题

一些潜在的风险:

  1. 队列大小(Count)的读取:如果 Queue<T> 正在被修改(例如,写线程在 Enqueue),另一个线程试图读取队列大小或进行 Dequeue 操作,可能会得到不一致的结果。因为写线程可能在修改队列时,读线程同时查看到一个不完全或不一致的队列状态。

  2. 数据一致性:尽管读写操作看似是顺序执行的,实际上在多个线程访问共享数据时,现代 CPU 和优化可能导致线程看到过时或不一致的数据(内存可见性问题)。因此,即使操作本身是序列化的,底层的硬件优化仍可能引发问题。

如何解决?

1. 使用锁 (lock)

通过使用 lock 确保 写操作读操作 不会同时进行,这样可以防止数据竞争和不一致性:

public class ThreadSafeQueue<T>
{
    private readonly Queue<T> queue = new Queue<T>();
    private readonly object lockObject = new object();

    public void Enqueue(T item)
    {
        lock (lockObject)
        {
            queue.Enqueue(item);
        }
    }

    public T Dequeue()
    {
        lock (lockObject)
        {
            if (queue.Count == 0)
                throw new InvalidOperationException("Queue is empty.");
            return queue.Dequeue();
        }
    }

    public int Count
    {
        get
        {
            lock (lockObject)
            {
                return queue.Count;
            }
        }
    }
}

在这个示例中,通过 lock 来确保写操作和读操作不会发生竞态条件。

2. 使用 ConcurrentQueue<T>

如果你不希望手动加锁,可以使用 ConcurrentQueue<T>,它是线程安全的,可以在多个线程中同时进行读写操作,保证数据的一致性和正确性:

using System.Collections.Concurrent;

var concurrentQueue = new ConcurrentQueue<int>();

// 写线程:入队
concurrentQueue.Enqueue(1);
concurrentQueue.Enqueue(2);

// 读线程:出队
if (concurrentQueue.TryDequeue(out int result))
{
    Console.WriteLine(result); // 安全地获取队列元素
}

ConcurrentQueue<T> 会自动管理线程同步,因此你不需要担心加锁的问题,它会确保多线程环境下的正确性。

总结:

  • 即使一个线程只负责写,另一个线程只负责读,Queue<T> 仍然 不保证线程安全,会有潜在的竞态条件和数据不一致问题。
  • 如果需要确保线程安全,可以使用 lock 来同步读写操作,或者使用 ConcurrentQueue<T> 来避免手动管理同步。推荐使用 ConcurrentQueue<T>,因为它是专为多线程设计并且已经实现了高效的线程安全。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为云deepseek大模型平台:deepseek满血版

华为云硅基流动使用Chatbox接入DeepSeek-R1满血版671B 1、注册&#xff1a; 华为云deepseek大模型平台注册&#xff1a;https://cloud.siliconflow.cn/i/aDmz6aVN 说明&#xff1a;填写邀请码的话邀请和被邀请的账号都会获得2000 万 Tokens&#xff1b;2个帐号间不会与其他关联…

import requests Pycharm 报错

#PyCharm安装requests失败解决方法 PyCharm安装request失败解决方法&#xff08;亲测有效&#xff09; import requests Pycharm 报错 尝试从系统终端运行此命令。确保使用为 D:\Python\venv\Scripts\python.exe 处的 Python 解释器安装的正确版本的 pip。失败一&#xff1…

基于云的物联网系统用于实时有害藻华监测:通过MQTT和REST API无缝集成ThingsBoard

论文标题 **英文标题&#xff1a;**Cloud-Based IoT System for Real-Time Harmful Algal Bloom Monitoring: Seamless ThingsBoard Integration via MQTT and REST API **中文标题&#xff1a;**基于云的物联网系统用于实时有害藻华监测&#xff1a;通过MQTT和REST API无缝集…

VMware converter standalone迁移windows老版本系统到esxi

最近因为有个客户有5台老服务器想淘汰掉换成新服务器&#xff0c;有多老呢&#xff1f;差不多20年了。比我干这个行业的时间还久。 老服务器的系统分别是&#xff1a; 1&#xff1a;3台windows server 2008 sp2 x64系统 2&#xff1a;2台windows server 2003 sp2 x32系统 新服务…

python学opencv|读取图像(七十五)人脸识别:Fisherfaces算法和LBPH算法

【1】引言 前序学习进程中&#xff0c;已经掌握了使用Eigenfaces算法进行的人脸识别。相关文章链接为&#xff1a; python学opencv|读取图像&#xff08;七十四&#xff09;人脸识别&#xff1a;EigenFaces算法-CSDN博客 在此基础上&#xff0c;学习剩余两种人脸识别算法&am…

【GaussTech技术专栏】GaussDB AI大模型在智能运维场景的应用

在数字化转型的浪潮中&#xff0c;数据库作为企业数据管理的核心&#xff0c;扮演着至关重要的角色。随着业务规模的扩大和数据量的激增&#xff0c;数据库运维的复杂性也随之增加。传统运维方法在确保数据高可用性、系统稳定性、性能优化及故障快速响应方面&#xff0c;面临着…

燧光 XimmerseMR SDK接入Unity

官网SDK文档连接&#xff1a; RhinoX Unity XR SDK 一&#xff1a;下载SDK 下载链接&#xff1a;RhinoX Unity XR SDK 二&#xff1a;打开Unity项目&#xff0c;添加Package 1、先添加XR Core Utilties包和XR Interaction Toolkit包 2、导 2、再导入下载好的燧光SDK 三&…

政安晨的AI大模型训练实践 九 - 熟悉LLaMA Factory的详细参数含义-基本概念理解一下

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 小伙伴铁子们&#xff0c;上手先熟悉起来训练工具的每一个参数&#xff0c;很重要。 参照我…

Arduino IDE编程ESP32-C3的Flash选项

用Arduino IDE为ESP32-C3编程 概述ESP32-C3的FLASH连接Arduino编程选项FLASH的QIO和DIO总结后记概述 买了CORE-ESP32-C3实验板,用Arduino IDE为板子编程。板子如下: 编程出现问题,串口打印输出: 13:56:22.927 -> E (25) boot: load partition table error! 13:56:22.…

SAP 代码扫描工具

描述&#xff1a; ZSCANNER是一个先进的代码分析工具&#xff0c;旨在提供对程序和功能模块内部工作的全面见解。它揭示了代码的技术细节&#xff0c;包括正在创建、读取、更新或删除的数据表&#xff08;CRUD操作&#xff09;&#xff0c;以及正在调用的类、功能模块和BAPI&a…

el-table树状表格,默认展开第一个节点的每一层

效果如图 <template><el-table:data"tableData"style"width: 100%":tree-props"{ children: children, hasChildren: hasChildren }":expand-row-keys"expandRowKeys"row-key"id"expand-change"handleExpan…

以ChatGPT为例解析大模型背后的技术

目录 1、大模型分类 2、为什么自然语言处理可计算&#xff1f; 2.1、One-hot分类编码&#xff08;传统词表示方法&#xff09; 2.2、词向量 3、Transformer架构 3.1、何为注意力机制&#xff1f; 3.2、注意力机制在 Transformer 模型中有何意义&#xff1f; 3.3、位置编…

I2C实践开发 ---【STM32-I2C-HDC1080温湿度采集系统】

I2C实践开发 — STM32-I2C-HDC1080温湿度采集系统 目录 I2C实践开发 --- STM32-I2C-HDC1080温湿度采集系统1. 引言2. 系统架构2.1 硬件架构2.2 软件架构 3. 代码分析3.1 I2C驱动文件 (i2c.h 和 i2c.c)3.2 HDC1080传感器驱动文件 (hdc1080.h 和 hdc1080.c) 4. 功能总结【HDC1080…

java毕业设计之医院门诊挂号系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的医院门诊挂号系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 医院门诊挂号系统的主要使用者…

[笔记.AI]大模型的蒸馏、剪枝、量化 | 模型压缩 | 作用与意义

上周简单整理了《deepseek-r1的不同版本&#xff08;满血版、蒸馏版、量化&#xff09;》&#xff0c;这次继续完善对其的认知——补充“剪枝”&#xff0c;并进一步整理蒸馏、剪枝、量化的作用与意义。 以下摘自与DeepSeek-R1在线联网版的对话 蒸馏、剪枝、量化是当前主流的三…

VMware按照的MacOS升级后无法联网

背景 3年前公司使用Flutter开发了一款app&#xff0c;现在app有微小改动需要重新发布到AppStore 问题 问题是原来的Vmware搭建的开发环境发布App失败了 提示&#xff1a;App需要使用xcode15IOS 17 SDK重新构建&#xff0c;这样的话MacOS至少需要升级到13.5 Xcode - 支持 - Ap…

量子计算的基本运算:Hadamard 门、CNOT 门、Pauli 门详解

量子计算是现代计算科学的前沿领域,它与经典计算机在处理信息的方式上有着本质的区别。量子计算机利用量子比特(qubit)的叠加态和量子纠缠等特性来进行计算,从而在某些特定任务上超越传统计算机。量子计算的核心运算单元是量子门,它们通过作用于量子比特来操控量子状态。本…

go http Client net/http

框架推荐 net/http go的内置http工具&#xff0c;可以构建client和server。 Slf4j Controller RequestMapping("/rest") public class RestTestController {GetMapping("/get")ResponseBodypublic String get(RequestBody SSHConnectParam param) throws…

Pycharm中断点使用技巧

1. 打开项目并准备代码 首先&#xff0c;打开 PyCharm 并加载你的 Python 项目&#xff0c;确保你已经有想要调试的 Python 代码文件。如&#xff1a; def add_numbers(a, b):result a breturn resultnum1 5 num2 3 sum_result add_numbers(num1, num2) print(f"Th…

【数据库系统概论】第第12章 并发控制

12.1 并发控制概述 并发控制是指数据库管理系统&#xff08;DBMS&#xff09;通过控制多个事务同时执行&#xff0c;保证数据的一致性和隔离性&#xff0c;避免事务间的相互干扰。 事务串行执行不能充分利用系统资源 并发执行的优点&#xff1a;能够减少处理机的空闲 时间&a…