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

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

 原子操作通常用于实现资源的引用计数,在TCP/IP协议栈的IP碎片处理中,就使用了引用计数,碎片队列结构struct 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实现)。

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

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

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

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

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


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

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

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值