volatile、mutex、gcc __sync_*原子操作 比较

1、volatile 取消了编译器优化, 强制从内存读 而不是从CPU缓存读

    常见例子,用  volatile 修饰 线程退出标志   (int  isThreadEnd),只是为了保证 isThreadEnd 的赋值不受编译器优化而忽略执行;

    因为 isThreadEnd 是个int flag,加上整型赋值的原子性(具体 [精彩] 对int变量的赋值是原子操作吗? ),因此多线程赋值即使不加锁,也能保证该flag 赋值正确

    【注意】这里的赋值正确,指的是不会出现一个线程赋了两个字节,另一个线程来读取数据的情况

  如以下程序,要加volatile ,才能保证 flag的赋值不受编译器优化而忽略执行

    class Gadget
{
public:
void Wait()
{
   while (!flag_)
   {
    Sleep(1000); // sleeps for 1000 milliseconds
   }
}
void Wakeup()
{
   flag_ = true;
}
...
private:
bool flag_;
};


2、多线程计数等等 ,还是需要线程锁(mutex)

    全局计数变量 iCount,为了保证iCount的准确性,多线程操作要加线程锁(mutex等等)

    【注意】这里的准确性,指的是常见的临界区变量需要线程锁(mutex)的情况

如下程序,加了volatile ,还是不能让 iCount 准确计数

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

volatile static int iCount = 0;

void *test_func(void *arg)
{
    int i = 0;
    for(i = 0; i < 20000; ++i)
    {
//        __sync_fetch_and_add(&iCount, 1);
        iCount++;
    }
    return NULL;
}

int main(int argc, const char *argv[])
{
    pthread_t id[20];
    int i = 0;

    for(i = 0; i < 20; ++i)
    {
        pthread_create(&id[i], NULL, test_func, NULL);
    }

    for(i = 0; i < 20; ++i)
    {
        pthread_join(id[i], NULL);
    }

    fprintf(stderr, "\n%s Line.%d-->iCount[%d]\n", __FILE__, __LINE__, iCount );
    return 0;
}


3、gcc 内置的 __sync_* 原子操作,其实跟线程锁是类似的功能

把上面的       //        __sync_fetch_and_add(&iCount, 1);       注释去掉,同时去掉           iCount++;

就能正确的计数;



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值