首页 > 其他分享 >什么是原子性和非原子性?

什么是原子性和非原子性?

时间:2024-05-28 14:34:41浏览次数:13  
标签:int 什么 counter 原子 pthread 操作 NULL

v1.0 2024年5月28日 发布于博客园

在嵌入式Linux C编程中,原子性(Atomicity)和非原子性(Non-Atomicity)是非常重要的概念,尤其是在处理多线程或多进程环境时。以下是对这两个概念的详细解释:

原子性(Atomicity)

原子性是指一个操作在执行过程中不可分割,要么完全执行,要么完全不执行。在多线程环境中,原子性操作不会被其他线程的操作打断。

例子:

  1. 简单的原子操作

    • 一些基本的读写操作在某些架构上是原子的。例如,在许多32位系统上,对32位整数的读写是原子的。
    int counter = 0;
    counter = 1;  // 这是一个原子操作(在许多架构上)
    
  2. 原子操作函数

    • 在嵌入式Linux中,可以使用GCC提供的内置原子操作函数,如__sync_fetch_and_add__sync_lock_test_and_set等。
    #include <stdio.h>
    
    int main() {
        int counter = 0;
        __sync_fetch_and_add(&counter, 1);  // 原子性加1操作
        printf("Counter: %d\n", counter);
        return 0;
    }
    
  3. 原子操作库

    • 使用Linux内核提供的原子操作库(atomic operations library),如atomic_t类型和相关的操作函数。
    #include <linux/atomic.h>
    
    atomic_t counter = ATOMIC_INIT(0);
    
    void increment_counter() {
        atomic_inc(&counter);  // 原子性加1操作
    }
    

非原子性(Non-Atomicity)

非原子性是指一个操作在执行过程中可能会被其他线程的操作打断。这种操作在多线程环境中可能导致竞争条件(Race Condition),从而引发数据不一致或其他并发问题。

例子:

  1. 非原子的复合操作

    • 例如,i++在许多架构上不是原子的,因为它实际上由多个步骤组成(读取、修改和写入)。
    int counter = 0;
    counter++;  // 这是一个非原子操作
    
  2. 竞争条件

    • 当多个线程同时执行非原子操作时,可能会导致不可预测的结果。
    #include <pthread.h>
    #include <stdio.h>
    
    int counter = 0;
    
    void* increment(void* arg) {
        for (int i = 0; i < 10000; i++) {
            counter++;  // 非原子操作,可能导致竞争条件
        }
        return NULL;
    }
    
    int main() {
        pthread_t t1, t2;
        pthread_create(&t1, NULL, increment, NULL);
        pthread_create(&t2, NULL, increment, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        printf("Counter: %d\n", counter);  // 结果可能不正确
        return 0;
    }
    

确保原子性的方法

  1. 使用原子操作函数

    • 使用GCC内置的原子操作函数,如__sync_fetch_and_add__sync_lock_test_and_set等。
  2. 使用原子操作库

    • 使用Linux内核提供的原子操作库(atomic operations library)。
  3. 使用互斥锁(Mutex)

    • 使用互斥锁来保护非原子操作,确保在多线程环境中操作的原子性。
    #include <pthread.h>
    #include <stdio.h>
    
    int counter = 0;
    pthread_mutex_t lock;
    
    void* increment(void* arg) {
        for (int i = 0; i < 10000; i++) {
            pthread_mutex_lock(&lock);
            counter++;  // 受互斥锁保护,确保原子性
            pthread_mutex_unlock(&lock);
        }
        return NULL;
    }
    
    int main() {
        pthread_t t1, t2;
        pthread_mutex_init(&lock, NULL);
        pthread_create(&t1, NULL, increment, NULL);
        pthread_create(&t2, NULL, increment, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_mutex_destroy(&lock);
        printf("Counter: %d\n", counter);  // 结果正确
        return 0;
    }
    

总结

  • 原子性:操作不可分割,要么全部执行,要么全部不执行,确保数据一致性和线程安全。
  • 非原子性:操作可能被打断,可能导致数据不一致,需要额外的同步机制来确保线程安全。

在嵌入式Linux C编程中,理解和正确使用原子性和非原子性对于编写安全有效的并发程序至关重要。

标签:int,什么,counter,原子,pthread,操作,NULL
From: https://www.cnblogs.com/zqingyang/p/18217958

相关文章

  • 【chisel】chisel中for (i <- 0 until N-2) {} 的用法,表示什么?
    在Chisel中,for(i<-0untilN-2){}是一个for循环的语法,它表示从0开始到N-2的整数(不包括N-2),并对每个整数i执行大括号{}内的代码块。这里的until是Scala语言的一个关键字,用于生成一个从起始值到结束值之前的所有整数的序列。在Chisel中,Scala的这个特性......
  • 什么?部署ClickHouse的服务器CPU利用率100%了?
    背景  某客户现场的ClickHouse所在服务器资源占用率100%了,引发了服务器告警。观察Grafana监控面板发现,从12点左右出现了大量的碎片写入,从而引起了相关指标的快速上升。  本文主要通过ClickHouse官方的系统表system.query_log表进行问题排查定位,结合Grafana监控面板最......
  • 京东二面:为什么Netty要造FastThreadLocal?
    FastThreadLocal从字面意义上来看,它是“Fast”+“ThreadLocal”的结合体,寓意为快速的ThreadLocal。那么,问题来了,Netty为什么要再造一个FastThreadLocal?FastThreadLocal运行快的原因是啥?除了快之外,它还有其他优势吗?1.先从ThreadLocal说起ThreadLocal线程本地变量,每个线程都......
  • WorldSpace下的合批策略与ScreenSpace有什么区别
    1)WorldSpace下的合批策略与ScreenSpace有什么区别2)在iOS上用Metal取代OpenGL的多么3)在动画蓝图中将两个或多个动画同时融合到同一个网格4)Mipmap如何限定层级这是第387篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答、社区帖子等技术知识点,助力大家更全面地掌握和......
  • 键入网址但网页显示,期间发生了什么?
    学习自http://https://xiaolincoding.com/network/1_base/what_happen_url.html#%E5%AD%A4%E5%8D%95%E5%B0%8F%E5%BC%9F-http生成HTTP请求信息浏览器解析URL(UniformResourceLoactor),生成发送给Web服务器的请求信息。查询服务器域名对应的IP地址---寻找目的地IPDNS服务......
  • 为什么中国的开发者都喜欢用 vue?
    Vue.js在中国的开发者中非常受欢迎,这主要有以下几个原因:易于学习:Vue.js的学习曲线相对较平缓,对于初学者来说更加友好。它的API和设计都非常直观,使得开发者可以快速上手并开始开发。灵活性:Vue.js设计为渐进式的,这意味着开发者可以根据项目的需要选择使用部分或全部的Vue.js功能......
  • 边缘计算|Hadoop——边缘计算和Hadoop是什么关系?
    边缘计算和Hadoop之间存在关联,但它们是两种不同的技术,分别应用于不同的计算场景。以下是它们之间关系的详细解释:定义与功能:边缘计算:边缘计算是指在靠近物或数据源头的一侧,采用网络、计算、存储、应用核心能力为一体的开放平台,就近提供最近端服务。它降低了延迟,节省了带宽,并允......
  • 原子上下文与中断上下文
    原子上下文与中断上下文目录原子上下文与中断上下文原子上下文(AtomicContext)中断上下文(InterruptContext)差异与联系原子上下文(AtomicContext)原子操作是一个在多线程环境中“不可分割”的操作,即该操作要么全部完成,要么完全不执行,不会出现只执行一部分的情况。原子操作在多线......
  • tar -zxvf是什么意思
    查看tar命令的详细解释mantar-z-x反之-c为压缩-v-f本文参考博客:tar-zxvf是什么意思......
  • golang为什么chan大部分是发送结构体,而不是其它比如string
     typetokenstruct{}typeGroupstruct{cancelfunc(error)wgsync.WaitGroupsemchantokenerrOncesync.Onceerrerror}func(g*Group)done(){ifg.sem!=nil{<-g.sem}g.wg.Done()}在Go语言中,通道(......