【无标题】

该文通过一个示例展示了C语言中volatile关键字的重要性,特别是在多线程操作共享变量时,确保编译器不会优化掉对内存的直接读写,防止程序因无法感知变量变化而出现死循环。当使用gcc进行O1或O2优化编译时,不使用volatile可能会导致问题。
摘要由CSDN通过智能技术生成

c语言volatile的作用是告诉编译器直接读取写入内存而不是寄存器或私有缓存
在多线程操作和比较变量并且gcc -O1或O2优化编译时,如果不给变量加volatile修饰,可能导致程序永远感知不到变量变化而导致程序死循环等待变量变化。
下面是例子:

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


typedef struct{
    volatile int headIndex;
    volatile int endIndex;
}oneWriteOneRead;

oneWriteOneRead owor = {0};
volatile int headCount = 0;
volatile int endCount = 0;
volatile long endWait = 0;
volatile long headWait = 0;

void* addThread()
{
    printf("addThread start\n");
    int headIndex = owor.headIndex;
    while (1)
    {
        if (headIndex < owor.endIndex)
        {
            headIndex++;
            owor.headIndex = headIndex;
            if (headIndex % 37 == 0)
            {
                headCount++;
            }
        }
        else
        {
            headWait++;
        }
    }
}

int main(void) 
{
    pthread_t threadId;
    pthread_create(&threadId, NULL, addThread, (void*)0);
    int endIndex = owor.endIndex;
    endIndex++;
    while (1)
    {
        if (endIndex - owor.headIndex < 37)
        {
            owor.endIndex = endIndex;   //因为每次调用owor.endIndex都读取或写入内存,所以用个中间变量可以减少内存操作??
            if (endIndex % 37 == 0)
            {
                endCount++;
                if (endCount == 100000)
                {
                    break;
                }
            }
            endIndex++;
        }
        else
        {
            endWait++;
        }
    }
    printf("owor.headIndex = %d, owor.endIndex = %d, headCount = %d, endCount = %d, headWait = %lld, endWait = %lld\n",
            owor.headIndex,      owor.endIndex,      headCount,      endCount,      headWait,        endWait);
    // sleep(1);
    printf("owor.headIndex = %d, owor.endIndex = %d, headCount = %d, endCount = %d, headWait = %lld, endWait = %lld\n",
            owor.headIndex,      owor.endIndex,      headCount,      endCount,      headWait,        endWait);
}

$ gcc -O2 -l pthread test.c
$ ./a.out
addThread start
owor.headIndex = 3700000, owor.endIndex = 3700000, headCount = 100000, endCount = 100000, headWait = 5664081, endWait = 1033531
owor.headIndex = 3700000, owor.endIndex = 3700000, headCount = 100000, endCount = 100000, headWait = 5703001, endWait = 1033531

如果去掉某个head开头变量的volatile修饰,主线程就读不到head变量的变化了,当然gcc -O0就没问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值