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. 加锁 = 安全执行 = 逻辑原子
相关推荐
晴天的雨.9922 分钟前
【Linux】Shell 命令以及运行原理+权限管理
linux·运维·服务器
djjjx.7 分钟前
Linux工具篇 (六):GDB 调试从底层逻辑到高阶实战
linux·运维·服务器·gdb
coward9127 分钟前
RK3576 双千兆 GMAC 驱动加载异常问题排查与总结
linux
幼儿园蛋小黄37 分钟前
从设备树到 ARM 驱动:嵌入式 Linux 驱动开发学习总结
linux·arm开发·驱动开发
dishugj1 小时前
HANA集群计划内切换与维护操作
java·linux·数据库
爱吃香菜的初学者3 小时前
十四.Linux——消息队列
linux·运维·开发语言
Apipi*10 小时前
30天速通Linux 第六章信号及信号处理
linux·运维·信号处理
天启HTTP11 小时前
爬虫防封核心原理:IP轮换机制与风控规避逻辑
linux·服务器·网络·爬虫·tcp/ip
广州浮点FLOATLIC13 小时前
许可证服务器迁移后软件打不开:研发 IT 怎样定位连接问题
linux·服务器·数据库
BLUcoding13 小时前
接口服务公网超时排查记录:SecureRandom 阻塞问题分析与解决
java·linux·springboot·aes·securerandom