volatile的原子性机制

volatile的定义是为了防止编译器对其进行优化。

1、volatile修饰符的用途

(1)用途

用途如下:
1) 外部设备寄存器映射后的内存——因为外部设备寄存器可能会由于外部设备的状态变化而改变,因此映射后的内存需要注明为volatile的;
2)多线程或异步访问的全局变量(原子机制);
3)嵌入式汇编——防止编译器对其优化;

(2)原子性分析

对于用途2)需要进一步分析。

当全局变量由锁保护的时候,该全局变量是不需要volatile的:
1)锁保证了临界区的串行;
2)锁的实现中有内存屏障,保证临界区访问全局变量为最新值。

当没有锁保护的全局变量是需要使用volatile修饰的。


代码如下:
static volatile int counter = 0;

void add_counter(void)
{
    ++counter;
}

汇编代码:
add_counter:
pushl %ebp
movl %esp, %ebp
movl counter, %eax//*
addl $1, %eax//*
movl %eax, counter//*
popl %ebp
ret

编译器会先把counter存入了寄存器eax,然后对eax进行操作,再将eax存入counter。
++counter不是原子性操作.同时有两个线程会修改这个计数器,这时这个counter必须由锁保护!

2、volatile修饰符的原子机制

volatile提供原子性机制:
1)保证访问该变量时,每次都是从内存中读取最新值,并不会使用寄存器缓存该值,每次都会从内存中读取。
2)对该变量的修改,并不提供原子性的保证。

(1)全局变量没使用volatile修饰符

counter没加上volatile修饰符的代码:
static int counter = 0;

void add_counter(void)
{
    for (; counter != 0x10; ++counter) {
        ++counter;
    }
}


然后看其汇编代码,需要是使用-O优化啊。
[fgao@fgao-vm-fc13 test]$ gcc -S -O test.c
add_counter:
pushl %ebp
movl %esp, %ebp
movl counter, %eax
cmpl $16, %eax
je .L4
.L5:
addl $2, %eax
cmpl $16, %eax
jne .L5
movl %eax, counter
.L4:
popl %ebp
ret

从汇编代码中,可以看出:
这时将counter的值存入eax,然后每次给eax加2,然后使用eax与16比较,来完成C代码中的for循环的工作。

(2)全局变量使用volatile修饰符

counter加上volatile修饰符的代码:
static volatile int counter = 0;

void add_counter(void)
{
    for (; counter != 0x10; ++counter) {
        ++counter;
    }
}

依然打开编译器的优化选项-O
[fgao@fgao-vm-fc13 test]$ gcc -S -O test.c
add_counter:
pushl %ebp
movl %esp, %ebp
movl counter, %eax
cmpl $16, %eax
je .L4
.L5:
movl counter, %eax
addl $1, %eax
movl %eax, counter
movl counter, %eax
addl $1, %eax
movl %eax, counter
movl counter, %eax
cmpl $16, %eax
jne .L5
.L4:
popl %ebp
ret

L5为对应C代码中的for循环的汇编实现。通过对比前一个汇编,我们很容易就发现了区别。虽然在执行counter递增的时候,两者都使用了寄存器eax。
每次访问counter的时候,前者会直接使用寄存器eax,而后者(使用volatile的时候)会重新从counter中读取最新值至eax,然后再使用eax。





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值