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. 加锁 = 安全执行 = 逻辑原子
相关推荐
倔强的石头1069 小时前
【Linux指南】基础IO系列(八):实战衔接 —— 给微型 Shell 添加完整重定向功能
linux·运维·服务器
try2find9 小时前
打印ascii码报错问题
java·linux·前端
Ujimatsu9 小时前
虚拟机安装Ubuntu 26.04.x及其常用软件(2026.4)
linux·运维·ubuntu
一直会游泳的小猫12 小时前
homebrew
linux·mac·工具·包管理
寒秋花开曾相惜12 小时前
(学习笔记)4.2 逻辑设计和硬件控制语言HCL(4.2.1 逻辑门&4.2.2 组合电路和HCL布尔表达式)
linux·网络·数据结构·笔记·学习·fpga开发
狂奔的sherry12 小时前
一次由 mount 引发的 Linux 文件系统“错觉”
linux·运维·服务器
小黑要努力13 小时前
智能音箱遇到的问题(一)
linux·运维·git
ch3nyuyu13 小时前
静态库和动态库的制作
linux·运维·开发语言
一口Linux14 小时前
Linux C编程 | 从0实现telnet获取程序终端控制权
linux·运维·c语言
willhuo14 小时前
Certbot工具在CentOS 7.9上申请和配置SSL证书完整教程
linux·centos·ssl