`

多线程的原子操作和线程数据共享

 
阅读更多
volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。

<wbr></wbr>

<wbr><span style="font-size:18px"></span><wbr><span style="font-size:18px">原子操作通常用于实现<span style="color:#FF0000">资源的引用计数</span>,在TCP/IP协议栈的IP碎片处理中,就使用了引用计数,碎片队列结构struct</span><wbr><span style="font-size:18px">ipq描述了一个IP碎片,字段refcnt就是引用计数器,它的类型为atomic_t,当创建IP碎片时(在函数ip_frag_create中),使用atomic_set函数把它设置为1,当引用该IP碎片时,就使用函数atomic_inc把引用计数加1。当不需要引用该IP碎片时,就使用函数ipq_put来释放该IP碎片,ipq_put使用函atomic_dec_and_test把引用计数减1并判断引用计数是否为0,如果是就释放IP碎片。函数ipq_kill把IP碎片从ipq队列中删除,并把该删除的IP碎片的引用计数减1(通过使用函数atomic_dec实现)。</span></wbr></wbr></wbr>

所谓原子操作,就是该操作绝不会在执行完毕前被任何其他任务或事件打断,也就说,它的最小的执行单位,不可能有比它更小的执行单位,因此这里的原子实际是使用了物理学里的物质微粒的概念。

<wbr>原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义都定义在内核源码树的include/asm/atomic.h文件中,它们都使用汇编语言实现,因为C语言并不能实现这样的操作。<wbr>原子操作主要用于实现资源计数,很多引用计数(refcnt)就是通过原子操作实现的。</wbr></wbr>

多线程编程用锁是普遍现象,貌似已经成为习惯。
但各线程最好是独立的,不需要同步机制的。
锁会消耗资源,而且造成排队,甚至死锁,尽量想办法避免。
非用不可时候,比如,实时统计各线程的负载情况,多个线程要对全局变量进行写操作。
请用 ++i ,因为它是一个原子操作。

---------------------------------------------------

同学对++i的原子性提出了质疑,并做了个测试程序,经过讨论得出结论:++i在多线程的程序中,在单核环境下,不一定是原子的,在多核环境下肯定不是原子的,我把这个当作原子操作用在了统计中,所以我得出的统计值是要比实际处理能力小很多的。。。亏大了。。等有新的数据再更正过来。。想想犯这个基本错误的原因,当初我们大学教授在讲++i是原子操作的时候,距离现在计算机环境发生了巨大变化。<wbr></wbr>++i原子性讨论<wbr></wbr>


解决线程冲突问题,除了加锁外,我们还需要对 m_bIsEncryptedBeforeSend变量的修改进行原子操作(其知识点在下文)才能保证一个线程(该线程在cpu A核上)改了,另一个线程(该线程可能不在cpuA核而在其他核上)能知道这种更改。 i++或者++i 而且为Int非 long,double类型

用volatile 变量不会带来任何好处,根本不能解决多线程共享数据冲突问题,反而会因为不优化而带来性能损降。

volatile修饰的变量仅仅是保证编译器不会优化这个变量,同时也不会放到cpu寄存器中,但似乎并没有说明必须从物理内存中取数据而不从cpu缓存取数据。


分享到:
评论

相关推荐

    java多线程安全性基础介绍.pptx

    java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...

    针对于Executor框架,Java API,线程共享数据

    Executor框架是Java并发编程中的一个重要工具,它提供了一种管理...原子操作在并发编程中具有重要的作用,可以保证多个线程对同一个变量的操作是线程安全的。 在两个线程之间共享数据,可以通过以下几种方式实现:

    92道Java多线程与并发面试题含答案(很全)

    Java并发编程的核心概念包括: 线程(Thread):线程是程序执行流的最小单元。...原子操作(Atomic Operations):原子操作是不可中断的操作,即在多线程环境中,这些操作要么完全执行,要么完全不执行。

    Java多线程安全问题和锁

    多线程安全问题和锁 文章目录多线程安全问题和锁线程在jvm中的特点锁的出现synchronized 关键字-监视器锁monitor lock死锁的产生和避免 什么是线程安全问题? 当多个线程同时操作同一个数据是,可能会出现数据不一样...

    C++11并发编程关于原子操作atomic的代码示例

    项目中经常用遇到多线程操作共享数据问题,常用的处理方式是对共享数据进行加锁,如果多线程操作共享变量也同样采用这种方式。 为什么要对共享变量加锁或使用原子操作?如两个线程操作同一变量过程中,一个线程执行...

    C#线程锁介绍源码

    1.几种同步方法的区别 lock和Monitor是.NET用一个特殊结构实现的,Monitor...这在抢先多线程操作系统中是很重要的,在这样的操作系统中,线程可以在从某个内存地址加载值之后但是在有机会更改 和存储该值之前被挂起。

    Java的线程安全内存模型.docx

    当 多个线程 同时共享同一个 全局变量 做 写 的操作时候,可能会受到其他线程的干扰,导致数据 脏读 。(数据一致性问题) 如何解决线程安全问题? 核心思想:在同一时刻,只能有一个线程执行。 通过加锁...

    Linux多线程同步方式

    而操作系统对于多线程不会自动帮我们串行化,所以需要我们通过操作系统提供的同步方式api,结合自己的业务逻辑,利用多线程提高性能的同时,保证业务逻辑的正确性。一般而言,linux下同步方式主要有4种,原子锁,...

    c#.net多线程编程教学——线程同步

    随着对多线程学习的深入,你可能觉得需要了解一些有关线程共享资源的问题. .NET framework提供了很多的类和数据类型来控制对共享资源的访问。 考虑一种我们经常遇到的情况:有一些全局变量和共享的类变量,我们需要...

    JAVA实现Modbus RTU或Modbus TCPIP数据采集.rar

    2.多线程之间为更方便的实现数据共享采用了共享相同内存地址空间的形式,并且是并发运行,导致多个线程可能会同时访问或修改其他线程正在使用的变量值,导致安全性,同时如果线程之间相互等待对方拥有的锁,会出现...

    linux之线程同步的概要介绍与分析

    在Linux操作系统中,线程同步是多线程编程中的一个核心概念,它确保了多个线程在访问共享资源时的正确性与一致性,避免了诸如数据竞争和竞态条件等问题。为了实现这一目标,Linux提供了一系列强大的线程同步机制和...

    Java并发面试题整理(答案)

    从程序运行效率的角度来看,单核 CPU 不但不会发挥出多线程的优势,反而会因为在单核 CPU 上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核 CPU 我们还是要应用多线程,就是为了防止阻塞。试想,...

    Java理论与实践:流行的原子

    本文介绍了要使用多处理器系统的功能,通常需要使用多线程构造应用程序。但是正如任何编写并发应用程序的人可以告诉你的那样,要获得好的硬件利用率,只是简单地在多个线程中分割工作是不够的,还必须确保线程确实大...

    Test2.java

    java多线程的通讯共享数据就是共享内存,共享内存主要有可见性和有序原子性。java 内存原型JMM解决可见有序,线程锁synchronized所解决它的原子性。 JMM内存原型:java可以在不同操作系统不同硬件存储逻辑下运行的...

    httpclient + jsoup java爬虫DEMO

    和线程池,最近任务是写爬虫,五百个网址,循环很慢,然后考虑用多线程,今天看了一下多线程,氛围继承thread 和实现runnuble接口,差不多这么拼写的,区别在于runnuble接口可以共享资源,当然,也就考虑到了线程...

    Java线程安全

    在多线程环境下,不同线程对同一份数据操作,就可能会产生不同线程中数据状态不一致的情况,这就是线程安全问题的定义或者说原因。要实现线程安全,需要保证数据操作的两个特性:原子性:对数据的操作不会受其他线程...

    php多进程框架-模拟java多线程接口simple-fork-php.zip

    获取进程状态(调用isAlive()方法)前,最好调用一个无阻塞的wait(false)进行一次回收,由于进程运行状态的判断不是原子操作,所以isAlive()方法不保证与实际状态完全一致 如果你不清楚在什么情况下...

    并发编程笔记20190526.docx

    第一章 线程基础、线程之间的共享和协作 3 一、基础概念 3 1. 什么是进程和线程 3 2. CPU核心数和线程数的关系 3 3. 澄清并行和并发 5 4. 多线程程序需要注意事项 6 二、认识Java里的线程 7 1. Java程序天生就是多...

    linux操作系统内核技术-uestc课件

     12熟悉进程地址空间的分区,mm_struct结构,vm_area_struct结构和操作,,进程的页表文件映射接口mmap原理和方法。(2小时)  13熟悉页cache和radix_tree,缓冲区cache,和pdflush内核线程原理。(2小时)

    Cpp-Concurrency-in-Action-2ed::books: C++ Concurrency in Action 2ed 笔记:C++111417 多线程技术

    、、、、死锁C++11线程库API线程管理(Managing thread)线程间共享数据(Sharing data between thread)同步并发操作(Synchronizing concurrent operation)C++ 内存模型和基于原子类型的操作(Th

Global site tag (gtag.js) - Google Analytics