【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)

news2024/10/7 14:32:11

请添加图片描述

  • 💌 所属专栏:【BES2500x系列】

  • 😀 作  者:我是夜阑的狗🐶

  • 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!

  • 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩

请添加图片描述

文章目录

  • 前言
  • 1 介绍
  • 2 功能特性
  • 3 同步与通信
      • 3.1 通信
  • 4 同步与通信
      • 4.1 消息队列
        • 4.1.1 定义
        • 4.1.2 创建
        • 4.1.3发送消息
      • 4.2 邮箱处理
        • 4.2.1 定义
        • 4.2.2 创建
        • 4.2.3 发送/释放邮件
        • 4.2.4 获取邮件
  • 总结


前言

  大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第4篇文章;
  今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
  专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。
  如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。


<<【系列文章索引】>>

1 介绍

  在嵌入式系统中,同步和通信是确保系统内各个组件协调工作的两个核心概念。它们对于实现高效、可靠的嵌入式应用至关重要。前面已经讲过同步概念了,接下来对通信概念进行简要说明。话不多说,那接下来就学习 RTX 系统中通信机制都有哪些吧,让我们原文再续,书接上回吧。😉

在这里插入图片描述

2 功能特性

  在实时操作系统(RTOS)中,任务管理和同步通信是关键组件,它们确保系统的高效和有序执行。本文将探讨这些概念,特别是线程管理、信号量、互斥锁、消息队列和邮箱处理。

  • 任务管理:RTX提供任务创建、调度和优先级管理,确保任务按照优先级及时执行。
  • 同步与通信:包括信号量、互斥锁、消息队列和邮箱,促进任务间的同步和数据交换。
  • 内存管理:内存池和动态内存分配,有效管理有限的系统资源。
  • 定时器服务:虚拟和硬件定时器,支持周期性任务和一次性事件触发。
  • 中断处理:保证中断服务的快速响应,同时保持任务的上下文安全。
  • 线程安全:通过内核级保护机制,防止多线程环境下的数据竞争和死锁。

3 同步与通信

3.1 通信

  通信是指嵌入式系统中不同组件或任务之间交换信息的过程。有效的通信机制对于分布式系统和多处理器系统尤为重要。嵌入式系统中常用的通信方式包括:

序号方法说明
1消息队列(Message Queues)任务间通过发送和接收带有数据的消息来通信,支持异步通信。
2管道(Pipes)一种半双工的数据传输方式,常用于进程间的通信。
3共享内存(Shared Memory)多个任务可以直接读写同一块内存区域,效率高但需要同步机制来避免冲突。
4总线(Buses)I2CSPIUART等硬件接口,用于设备间的数据传输。
5远程过程调用(RPC)允许程序调用网络中另一台计算机上的子程序,模拟本地调用。
6中断(Interrupts)硬件触发的事件,用于通知 CPU 处理紧急或外部事件,是一种快速的通信方式。

  同步和通信机制的选择取决于嵌入式系统的具体需求,包括实时性、资源限制、复杂度以及系统的可靠性要求。合理设计同步和通信策略,是保证嵌入式系统高效稳定运行的关键。

4 同步与通信

4.1 消息队列

  消息队列允许线程间安全地传递固定大小的消息,提供了异步通信的方式。

4.1.1 定义

  消息队列允许线程安全地发送和接收固定大小的数据块。队列维护发送和接收的顺序。一般在文件开头会看到这样的定义:osMessageQDef

  • 代码
// 定义一个名为app_test1_queue的消息队列,可存储128个uint32_t类型的元素。
osMessageQDef(app_test1_queue, 128, uint32_t);

// 声明一个osMessageQId类型的变量app_test1_queue_id,用于保存消息队列的句柄。
// 在程序运行时,需要通过调用相关API初始化并获取有效的句柄值。
osMessageQId app_test1_queue_id = NULL;

  这段代码首先使用 osMessageQDef 宏定义了一个名为 app_test1_queue 的消息队列,它可以存储128个32位无符号整数。然后声明了一个变量 app_test1_queue_id ,用于存储消息队列的标识符(句柄),初始值设为 NULL 。在实际应用中,需要通过操作系统提供的API来初始化这个消息队列,并将返回的句柄赋值给app_test1_queue_id

/**
 * 定义一个消息队列。
 * 
 * 这个宏用于静态定义一个消息队列,它会创建一个静态队列控制块和一个用于存储消息的数据缓冲区。
 * 
 * @param name 消息队列的名称。
 * @param queue_sz 队列中能容纳的消息数量。
 * @param type 消息队列中每条消息的数据类型。
 */
#define osMessageQDef(name, queue_sz, type) \
static StaticQueue_t os_mq_cb_##name; \
static uint32_t os_mq_data_##name[(queue_sz) * sizeof(type)]; \
const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), \
  { NULL, 0U, (&os_mq_cb_##name), sizeof(StaticQueue_t), \
              (&os_mq_data_##name), sizeof(os_mq_data_##name) } }

  此宏定义了三个静态变量:一个静态队列控制块,一个消息数据数组,和一个用于OS的消息队列定义结构体。这个结构体包含了队列的大小、指针到静态队列控制块和消息数据数组的地址,以及这些数组的大小。这使得在系统运行时能够直接使用这个消息队列而无需动态分配内存。

  • 参数/函数讲解
序号参数/函数说明
1osMessageQId声明变量,用于存储消息队列的标识符(句柄),初始值设为NULL。
2osMessageQDef定义了静态变量:静态队列控制块,消息数据数组和用于OS的消息队列定义结构体
4.1.2 创建

  通过 osMessageQueueCreate() 函数创建消息队列,指定队列容量和消息大小。

  • 代码
/**
 * 初始化app_test1_queue消息队列。
 *
 * 这个函数负责创建名为app_test1_queue的消息队列,并将成功创建的句柄保存到全局变量app_test1_queue_id。
 * 如果消息队列创建失败,它会记录错误信息并返回-1。
 *
 * @return
 *   - 0: 消息队列创建成功。
 *   - -1: 创建消息队列失败。
 */
static int32_t app_test1_queue_init(void)
{
    // 使用osMessageCreate函数创建消息队列,并将句柄保存到全局变量
    app_test1_queue_id = osMessageCreate(osMessageQ(app_test1_queue), NULL);

    // 检查创建是否成功,如果失败则打印错误信息并返回-1
    if (app_test1_queue_id == NULL) {
        TRACE(0, "Failed to Create app_test_thread1_queue");
        return -1;
    }

    // 创建成功,返回0
    return 0;
}

  这段代码定义了一个名为 app_test1_queue_init 的静态函数,用于初始化之前定义的消息队列app_test1_queue 。它通过调用o sMessageCreate 函数创建消息队列,并检查返回的句柄是否有效。如果创建失败,它会记录错误信息并返回 -1 ;否则,返回 0 表示成功。

  • 参数/函数讲解
序号参数/函数说明
1osMessageCreate创建消息队列
4.1.3发送消息

  使用 osMessageQueueSend()osMessageQueuePut() 函数向队列发送消息。

  • 代码
/**
 * 尝试向app_test1_queue中发送消息。
 *
 * 此函数检查消息队列是否有足够的空间接收至少6条消息。如果队列有足够空间,
 * 它将向队列中放入一个值为0xFF的消息,不设置优先级。
 *
 * 注意:这个函数没有处理消息队列满的情况,因此在队列满时不会阻塞。
 */
void app_test1_queue_put(void)
{
    // 检查消息队列是否有超过5个空闲槽位
    if (osMessageGetSpace(app_test1_queue_id) > 5) {
        // 向消息队列app_test1_queue_id中插入一个值为0xFF的消息,优先级设为0
        osMessagePut(app_test1_queue_id, 0xFF, 0);
    }
}

  这个函数 app_test1_queue_put 尝试将一个值为 0xFF 的消息放入名为 app_test1_queue 的消息队列中。首先,它检查队列是否有足够的空间容纳至少6个新消息。如果满足条件,就调用 osMessagePut 将消息放入队列,否则不做任何操作。注意,这个函数没有处理队列已满的情况,所以如果队列已满,消息将不会被发送,也不会阻塞调用线程。

  • 参数/函数讲解
序号参数/函数说明
1osMessageGetSpace检查消息队列的空闲槽位
2osMessagePut将消息放入队列

4.2 邮箱处理

  邮箱是用于线程间交换结构化数据的对象池。每个邮箱包含一组预先分配的内存块,线程可以申请、发送和接收这些内存块。

4.2.1 定义

  一般在文件开头会看到这样的定义:osMailQDef

  • 代码
osMailQDef (app_test1_mailbox, APP_TEST1_MAX_MAILBOX, APP_TEST1_MAIL); 
/**
 * app_test1_mailbox: 邮箱队列定义
 *
 * 使用osMailQDef宏定义一个名为'app_test1_mailbox'的邮箱队列,最大邮件数为APP_TEST1_MAX_MAILBOX,
 * 邮件类型为APP_TEST1_MAIL。
 */

// 邮箱队列ID,用于后续操作
static osMailQId app_test1_mailbox_id = NULL;

/**
 * app_test1_mail_alloc - 分配并初始化一个APP_TEST1_MAIL类型的邮件
 *
 * @param mail 指向邮件指针的指针,用于存放新分配的邮件地址。
 *
 * 返回值: 成功分配时返回0,失败则返回非0值。
 *
 * 此函数为内部使用,负责从'app_test1_mailbox'邮箱队列中分配一个新的邮件,并将其地址存储在
 * 输入参数'mail'指向的变量中。具体实现省略。
 */
static int app_test1_mail_alloc(APP_TEST1_MAIL** mail)
{
    // ...
}

  osMailQDef 定义了一个名为 app_test1_mailbox 的邮箱队列,用于存储 APP_TEST1_MAIL 类型的数据。APP_TEST1_MAX_MAILBOX 定义了邮箱队列可容纳的最大邮件数量。这个邮箱队列可以用于多线程或任务之间的数据通信,确保数据安全地传递。

/**
 * 定义一个邮箱队列。
 * 
 * 该宏用于静态定义一个邮箱队列以及相关的OS邮箱队列结构体。它为指定的邮箱队列分配内存,
 * 并初始化OS邮箱队列结构体。
 * 
 * @param name 邮箱队列的名称。
 * @param queue_sz 邮箱队列中邮件的最大数量。
 * @param type 邮件中元素的类型。
 */
#define osMailQDef(name, queue_sz, type) \
static uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
osMailQDef_t os_mailQ_def_##name = \
{ {(queue_sz), sizeof(type), (os_mailQ_m_##name)}, NULL, {NULL} }

  在上述宏定义中:

  (1) 第一部分定义了一个静态数组 os_mailQ_m_##name,用于存储邮箱队列中的邮件。数组大小根据邮件类型 type 的大小和队列大小 queue_sz 动态计算得出。
  (2) 第二部分定义了一个 osMailQDef_t 类型的结构体 os_mailQ_def_##name,其中包含了邮箱队列的配置信息,如队列大小、邮件类型大小以及邮件存储区的指针。

  • 参数/函数讲解
序号参数/函数说明
1osMailQDef定义了的邮箱队列,用于存储 APP_TEST1_MAIL 类型的数据
2app_test1_mailbox_id是一个全局变量,用于存储邮箱队列的标识符,方便后续操作
3app_test1_mail_alloc用于从 app_test1_mailbox 中分配一个新的邮件,并将分配的邮件地址通过参数 mail 返回
4os_mailQ_m_##name用于存储邮箱队列中的邮件
5osMailQDef_t定义结构体,其中包含了邮箱队列的配置信息
4.2.2 创建

  通过 osMailQCreate() 函数创建邮箱,指定邮箱的大小和数据类型。

  • 代码
/**
 * app_test1_mailbox_init - 初始化app_test1_mailbox邮箱队列
 *
 * @return: 成功初始化时返回0,失败则返回-1。
 *
 * 此函数用于初始化之前定义的'app_test1_mailbox'邮箱队列。它调用osMailCreate函数创建邮箱队列,
 * 并将返回的邮箱ID存储在全局变量'app_test1_mailbox_id'中。如果创建失败,函数会输出错误信息
 * "Failed to Create app_test_thread1_mailbox",并返回-1表示初始化失败。
 */
static int32_t app_test1_mailbox_init(void)
{
    app_test1_mailbox_id = osMailCreate(osMailQ(app_test1_mailbox), NULL);

    if (app_test1_mailbox_id == NULL) {
        TRACE(0, "Failed to Create app_test_thread1_mailbox");
        return -1;
    }

    return 0;
}

  这个函数 app_test1_mailbox_init 负责初始化之前通过 osMailQDef 宏定义的 app_test1_mailbox 邮箱队列。如果初始化成功,它将返回0;如果失败(即无法创建邮箱队列),它会打印错误信息并返回-1。

  • 参数/函数讲解
序号参数/函数说明
1osMailCreate创建邮箱队列
4.2.3 发送/释放邮件

  使用 osMailQAlloc() 分配邮箱中的空间,然后用 osMailPut() 发送邮件。

  • 代码
/**
 * app_test1_mail_send - 发送一个APP_TEST1_MAIL类型的邮件到app_test1_mailbox
 *
 * @param mail 需要发送的邮件对象指针。
 *
 * 返回值: 成功发送时返回0,失败则返回非0值。
 *
 * 此函数用于将一个APP_TEST1_MAIL类型的邮件对象发送到'app_test1_mailbox'邮箱队列中。
 * 具体实现省略,可能涉及到邮箱队列的同步原语以保证线程安全。
 */
static int app_test1_mail_send(APP_TEST1_MAIL* mail)
{
    // ...
}

/**
 * app_test1_mail_free - 释放app_test1_mailbox中的一个邮件对象
 *
 * @param mail_p 已分配的邮件对象指针。
 *
 * 返回值: 成功释放时返回0,失败则返回非0值。
 *
 * 此函数用于释放'app_test1_mailbox'邮箱队列中已分配的一个邮件对象,以便于后续再使用。
 * 具体实现省略,可能涉及邮箱队列的同步原语以保证线程安全。
 */
static int app_test1_mail_free(APP_TEST1_MAIL* mail_p)
{
    // ...
}
  • 参数/函数讲解
序号参数/函数说明
1app_test1_mail_send用于向 app_test1_mailbox 邮箱队列中发送邮件
2app_test1_mail_free用于向 app_test1_mailbox 邮箱队列中释放已分配的邮件
4.2.4 获取邮件

  线程通过 osMailGet() 函数获取邮件,可以选择等待或立即返回。

  • 代码
/**
 * @brief          获取应用测试1的邮件对象
 * 
 * @description    该函数从内部数据结构中获取一个`APP_TEST1_MAIL`类型的邮件对象。
 *                 如果邮件可用,它将分配内存并填充邮件内容,然后将其指针返回。
 * 
 * @param[out]     mail_p     指向接收`APP_TEST1_MAIL`结构体指针的指针。
 *                            如果成功获取邮件,此参数将被设置为有效邮件对象的指针。
 * 
 * @return         成功获取邮件对象返回0,否则返回非0错误代码:
 *                 -1:邮件队列为空
 *                 -2:内存分配失败
 *                 其他值:可能表示其他错误情况
 *
 * @note           实现应考虑线程安全,可能需要加锁来保护数据结构。
 *                 如果队列为空,可以选择阻塞等待,直到有新邮件到达。
 */
static int app_test1_mail_get(APP_TEST1_MAIL** mail_p)
{
    // 实现获取邮件对象的逻辑,包括检查队列、分配内存、填充邮件内容等
    // ...

    if (/* 邮件队列为空或分配内存失败等错误条件 */) {
        return -1; // 或者 -2
    }

    return 0; // 成功获取邮件
}

  app_test1_mail_get 函数用于从 app_test1_mailbox 邮箱队列中取出一个邮件对象。当邮箱队列为空时,函数可能阻塞等待,直到有新的邮件可供消费。函数返回0表示成功获取邮件,非0值表示队列为空或出现错误。具体实现细节被省略,实际操作中可能需要考虑线程同步问题。

  • 参数/函数讲解
序号参数/函数说明
1app_test1_mail_get用于从邮箱队列中取出一个邮件对象

<<【系列文章索引】>>

请添加图片描述


总结

  感谢观看,这里就是 同步与通信篇 – 消息队列和邮箱处理,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹

在这里插入图片描述

  也欢迎你,关注我。👍 👍 👍

  原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉

更多专栏订阅:

  • 😀 【LeetCode题解(持续更新中)】

  • 🥇 【恒玄BES】

  • 🌼 【鸿蒙系统】

  • 💎 【蓝牙协议栈】

  • 🎃 【死机分析】

  • 👑 【Python脚本笔记】

  • 🚝 【Java Web项目构建过程】

  • 💛 【微信小程序开发教程】

  • 【JavaScript随手笔记】

  • 🤩 【大数据学习笔记(华为云)】

  • 🦄 【程序错误解决方法(建议收藏)】

  • 🔐 【Git 学习笔记】

  • 🚀 【软件安装教程】



订阅更多,你们将会看到更多的优质内容!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

容器内存

一、容器内存概述 容器本质上还是一个进程&#xff0c;是一个被隔离和限制的进程。因此容器内存和进程内存在表现形式上其实是一样的&#xff0c;这块主要涉及三部分内容&#xff1a;RSS&#xff0c;page cache和swap这三部分&#xff0c;容器基于memory Cgroup对内存进行限制…

k8s部署单机版mysql8

一、创建命名空间 # cat mysql8-namespace.yaml apiVersion: v1 kind: Namespace metadata:name: mysql8labels:name: mysql8# kubectl apply -f mysql8-namespace.yaml namespace/mysql8 created# kubectl get ns|grep mysql8 mysql8 Active 8s二、创建mysql配…

某网页gpt的JS逆向

原网页网址 (base64) 在线解码 aHR0cHM6Ly9jbGF1ZGUzLmZyZWUyZ3B0Lnh5ei8 逆向效果图 调用代码&#xff08;复制即用&#xff09; 把倒数第三行换成下面的base64解码 aHR0cHM6Ly9jbGF1ZGUzLmZyZWUyZ3B0Lnh5ei9hcGkvZ2VuZXJhdGU import hashlib import time import reques…

Python学习篇:PyCharm的基本使用教程(二)

目录 1 前言 2 创建Python项目 3 创建Python文件 4 编写 Hello World 并运行 5 PyCharm界面简介 1 前言 PyCharm的使用贯穿整个Python的学习&#xff0c;所以单独拿出来出教程不合适&#xff0c;说多了对于新手来说也还是不明白&#xff0c;这里我们先从学习开始前大家需…

【仪器仪表】 矢量网络分析仪 Vector Network Analyzer

主要功能&#xff1a; 测量S参数&#xff1a; S11&#xff08;输入反射系数&#xff09;&#xff1a;测量输入端口的反射。S21&#xff08;正向传输系数&#xff09;&#xff1a;测量从输入端口到输出端口的传输。S12&#xff08;反向传输系数&#xff09;&#xff1a;测量从输…

【后端面试题】【中间件】【NoSQL】MongoDB的配置服务器、复制机制、写入语义和面试准备

MongoDB的配置服务器 引入了分片机制之后&#xff0c;MongoDB启用了配置服务器(config server) 来存储元数据&#xff0c;这些元数据包括分片信息、权限控制信息&#xff0c;用来控制分布式锁。其中分片信息还会被负责执行查询mongos使用。 MongoDB的配置服务器有一个很大的优…

全网小视频去水印接口使用说明

一、请求地址&#xff1a; https://www.lytcreate.com/api/qsy/ 二、请求方式&#xff1a;POST 三、请求体&#xff1a;JSON body {"token": "个人中心的token","url": "视频分享地址"} token获取地址&#xff0c;访问&#xff…

DP:子序列问题

文章目录 什么是子序列子序列的特点举例说明常见问题 关于子序列问题的几个例题1.最长递增子序列2.摆动序列3.最长递增子序列的个数4.最长数对链5.最长定差子序列 总结 什么是子序列 在计算机科学和数学中&#xff0c;子序列&#xff08;Subsequence&#xff09;是指从一个序列…

继承QAbstractListModel,结合QListView

这里想要写一个QAbstractListModel的子类&#xff0c;学习一下如何实例化QAbstractListModel。 QAbstractListModel子类化-CSDN博客 QVariant与自定义类型互转之奇巧淫技_qt 类型转 qvariant-CSDN博客 #pragma once#include <QStyledItemDelegate> #include <qmeta…

012-GeoGebra基础篇-构造圆的切线

前边文章对于基础内容已经悉数覆盖了&#xff0c;这一篇我就不放具体的细节&#xff0c;若有需要可以复刻一下 目录 一、成品展示二、算式内容三、正确性检查五、文章最后 一、成品展示 二、算式内容 A(0,0) B(3,0) c: Circle(A,B) C(5,4) sSegment(A,C) DMidpoint(s) d: Circ…

javaEE——Servlet

1.web开发概述 所谓web开发,指的是从网页中向后端程序发送请求,与后端程序进行交互 2.java后端开发环境搭建 web后端(javaEE)程序需要运行在服务器中的&#xff0c;这样前端才可以访问得到 3.服务器是什么&#xff1f; ①服务器就是一款软件&#xff0c;可以向其发送请求&#…

分解+降维+预测!多重创新!直接写核心!EMD-KPCA-Transformer多变量时间序列光伏功率预测

分解降维预测&#xff01;多重创新&#xff01;直接写核心&#xff01;EMD-KPCA-Transformer多变量时间序列光伏功率预测 目录 分解降维预测&#xff01;多重创新&#xff01;直接写核心&#xff01;EMD-KPCA-Transformer多变量时间序列光伏功率预测效果一览基本介绍程序设计参…

嵌入式学习——硬件(Linux系统在2440上的启动)——day57

1. Linux2.6系统在s3c2440上的启动过程分三个阶段 1.1 启动u-boot 1.2 启动Linux内核 1.3 挂载根文件系统 2. bootloader 2.1 定义 bootloader的本质是一个裸机程序&#xff0c;bootlood专门是为了能够正确地启动linux操作系 统&#xff0c;在系统初上电时需要对系统做一些…

中霖教育怎么样?咨询工程师备考技巧

中霖教育怎么样?咨询工程师备考技巧 在备考咨询工程师的过程中&#xff0c;掌握正确的方式方法能够少走很多弯路&#xff0c;所以想取得好成绩采用恰当的备考技巧是非常重要的。 1、了解题型及考试结构 在准备阶段&#xff0c;理解各类型题目的特征和作答要求&#xff0c;确…

github仓库的基本使用-创建、上传文件、删除

1.第一步 先点击左侧菜单栏的远程仓库 2.点击NEW 3.创建仓库 然后点击右下角的 CREATE 4.点击code 点击SSH,然后我出现了You don’t have any public SSH keys in your GitHub account. You can add a new public key, or try cloning this repository via HTTPS. 1&#xff…

【JavaEE精炼宝库】多线程进阶(2)synchronized原理、JUC类——深度理解多线程编程

一、synchronized 原理 1.1 基本特点&#xff1a; 结合上面的锁策略&#xff0c;我们就可以总结出&#xff0c;synchronized 具有以下特性(只考虑 JDK 1.8)&#xff1a; 开始时是乐观锁&#xff0c;如果锁冲突频繁&#xff0c;就转换为悲观锁。 开始是轻量级锁实现&#xff…

成人职场商务英语学习柯桥外语学校|邮件中的“备注”用英语怎么说?

在英语中&#xff0c;"备注"通常可以翻译为"Notes" 或 "Remarks"。 这两个词在邮件中都很常用。例如: 1. Notes Notes: 是最通用和最常见的表达&#xff0c;可以用在各种情况下&#xff0c;例如&#xff1a; 提供有关电子邮件内容的附加信息 列…

Mysql并发控制和日志

文章目录 一、并发控制锁机制事务&#xff08;transactions&#xff09;事务隔离级别 二、日志事务日志错误日志通用日志慢查询日志二进制日志 备份在线查看二进制离线查看二进制日志 一、并发控制 锁机制 锁类型&#xff1a; 读锁&#xff1a;共享锁&#xff0c;也称为 S 锁…

ANSYS新能源汽车动力电池仿真应用案例

燃料电池是一种非燃烧过程的电化学能转换装置&#xff0c;将氢气&#xff08;等燃料&#xff09;和氧气的化学能连续不断地转换为电能&#xff0c;是发电设备而非储能设备。 根据电解质的不同&#xff0c;分为碱性燃料电池AFC、磷酸燃料电池PAFC、熔融碳酸盐燃料电池MCFC、固体…

电信NR零流量小区处理

【摘要】随着目前网络建设逐步完善&#xff0c;5G用户的不断发展&#xff0c;针对零流量小区的分析及处理存在着必要性&#xff0c;零流量小区的出现既是用户分布及行为的直观体现&#xff0c;也是发展用户的一个指引&#xff0c;同时也能发现设备的一些故障。一个站点的能够带…