linux——原子操作

一、原子操作概念

1. 什么是原子操作?

原子操作 = 不可被中断的操作就像原子是不可分割的最小单位一样。

CPU 执行原子操作时:

  • 一步完成
  • 执行期间不会被线程切换打断
  • 要么完全执行完,要么完全没执行
  • 不会出现 "执行一半被抢走 CPU" 的情况

2. 哪些是原子操作?

  • 简单赋值:a = 100;
  • 简单读取:int b = a;

3. 哪些 不是 原子操作?

这些操作会被线程打断:

  • a = b + 100; (读 → 算 → 写,三步)
  • i++; (读 → 加 → 写)
  • 链表插入、链表删除
  • printf() 不是原子操作(内部复杂)
  • malloc/free 不是原子操作

只要不是一步 CPU 指令,就不是原子操作!

二、为什么非原子操作必须加锁?

因为:非原子操作 = 多步指令 = 可能执行到一半被抢走 CPU一旦被抢走,数据就会错乱、崩溃、覆盖、丢失。

三、用两个示例代码讲清楚

我们以链表头插法为例:

复制代码
newNode->next = head;
head = newNode;

这两行代码 不是原子操作!必须连续执行,不能被打断。

示例代码 1:不加锁(错误!)

复制代码
void* producer(void *arg)
{
    while(1)
    {
        // 创建节点(原子与否不重要)
        Node *newNode = (Node*)malloc(sizeof(Node));
        newNode->data = rand()%100;

        // ==========================
        // 这两行不是原子操作!!!
        newNode->next = head;
        head = newNode;
        // ==========================

        printf("+++product: %d\n", newNode->data);

        sleep(rand()%3);
    }
    return NULL;
}

错误原因:

newNode->next = head;head = newNode;不是原子操作!

两个线程同时执行时,可能:

  • 线程 A 刚执行完第一行

  • CPU 被抢走

  • 线程 B 也修改 head

  • 回来后线程 A 继续执行 → 链表断了、节点丢了、程序崩溃!

结论:

多线程同时操作链表,不加锁 = 程序必定崩溃 / 数据错乱

示例代码 2:加锁(正确!)

复制代码
void* producer(void *arg)
{
    while(1)
    {
        Node *newNode = (Node*)malloc(sizeof(Node));
        newNode->data = rand()%100;

        // 加锁(开始原子区)
        pthread_mutex_lock(&mutex);

        // 这两行被锁保护 → 变成逻辑原子
        newNode->next = head;
        head = newNode;
        printf("+++product: %d\n", newNode->data);

        // 解锁
        pthread_mutex_unlock(&mutex);

        sleep(rand()%3);
    }
    return NULL;
}

锁把两行代码变成 "逻辑原子操作"

  • 同一时间只有一个线程能执行
  • 执行时不会被其他线程打断
  • 要么两行都执行完,要么都不执行
  • 链表永远安全、不会崩溃、不会断链

四、核心总结

  1. 原子操作:不可被中断的一步操作
  2. 多步操作(链表增删、i++)不是原子操作
  3. 非原子操作在多线程下必须加锁
  4. 锁可以让多步指令变成 "逻辑上的原子操作"
  5. 不加锁 = 线程切换打断 = 数据混乱 / 程序崩溃
  6. 加锁 = 安全执行 = 逻辑原子
相关推荐
kong@react4 小时前
Rocky Linux 10.2 全面解析:企业级 CentOS 替代方案及保姆级docker安装
java·linux·运维·docker
凡人叶枫4 小时前
Effective C++ 条款07:为多态基类声明 virtual 析构函数
linux·c语言·开发语言·c++
凡人叶枫5 小时前
Effective C++ 条款10:令 operator= 返回一个 reference to *this
java·linux·服务器·开发语言·c++·effective c++
|_⊙5 小时前
Linux 中断
linux
Championship.23.246 小时前
Linux 3.0 音频机制深度解析:ALSA基础架构与传统音频驱动模型
linux·运维·音视频·alsa
Tian_Hang6 小时前
Linux基础知识(四)
linux·ide·驱动开发·计算机视觉·硬件工程·动画
HLC++6 小时前
Linux文件操作
linux·运维·服务器
晚风予卿云月7 小时前
【Linux】进程控制(二)——进程等待 全方位详解
linux·运维·服务器·进程控制·进程等待
上天_去_做颗惺星 EVE_BLUE7 小时前
【新 Linux 服务器上手全攻略】系统巡检、存储规划与开发环境初始化
linux·运维·服务器·ubuntu·macos·centos
Titan20247 小时前
Linux文件系统
linux·服务器