免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 南海一钓叟
打印 上一主题 下一主题

那为大侠给俺讲讲cache和volatie变量的关系 [复制链接]

论坛徽章:
0
71 [报告]
发表于 2008-03-07 10:59 |只看该作者
原帖由 飞雪横天 于 2008-3-7 10:57 发表



唉, 那多线程之间的共享变量到底如何处理?

以我的想法, 多线程下共享变量缓冲在cache当中, 由于所有线程共享内存,所以所有线程访问同一个变量时都是访问同一个cache,因此

应该不需要使用volatile,  ...


你是没看我的留言还是没看懂我在说什么?

论坛徽章:
0
72 [报告]
发表于 2008-03-07 11:02 |只看该作者
原帖由 flw2 于 2008-3-7 10:53 发表


不是你上面这个意思

while(threadrunning == 0)
{
    pthread_exit(NULL);
}

编译器不能把threadrunning优化到寄存器,否则pthread_exit要是修改这个变量咋办?虽然pthread_exit不会修改你这个全 ...


可是下面这个程序, 您如何解释"while(total < 100) ", 莫非此时编译器就知道不会修改total,所以到cache取值?

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sched.h>
#include <sys/time.h>

#ifndef VOLATILE
#define VOLATILE
#endif
VOLATILE int    total = 0;  /* record the handle running times */

void handle(int signo)
{
    if(signo == SIGALRM)
    {
        printf("Total = %d\n", total);
        exit(0);
    }

    total++;
}

int main(int argc, char* argv[])
{
    VOLATILE unsigned   x = 0;
    VOLATILE int        i, j;
    struct sched_param  param;
    struct itimerval    val;

    val.it_interval.tv_sec = 0;
    val.it_interval.tv_usec = 10000;    // 10 ms
    val.it_value.tv_sec = 0;
    val.it_value.tv_usec = 10000;       // 10 ms
    setitimer(ITIMER_VIRTUAL, &val, NULL);
    param.sched_priority = 99;
    if(sched_setscheduler(0, SCHED_RR, &param) == -1)
    {
        perror("setting priority");
        exit(1);
    }

#define BIGNUM  (1000)
    alarm(20);
    signal(SIGALRM, handle);
    signal(SIGVTALRM, handle);
    while(total < 100)
    {
        for(i = 0; i < BIGNUM; i++)
        {
            for(j = 0; j < BIGNUM; j++)
                x = x + j;
        }
    }

    printf("x = %u\n", x);              // so optimizers doesn't throw away the loop
    printf("total = %d\n", total);

    return 0;
}

论坛徽章:
0
73 [报告]
发表于 2008-03-07 11:03 |只看该作者
原帖由 flw2 于 2008-3-7 10:59 发表


你是没看我的留言还是没看懂我在说什么?


呵呵, 这个是没看到,我写帖子的时候你帖子还没回呢

论坛徽章:
0
74 [报告]
发表于 2008-03-07 11:06 |只看该作者
原帖由 飞雪横天 于 2008-3-7 10:08 发表


看了这篇文章, 我倒是对volatile的理解更加糊涂了.

不同线程中对同一个变量的访问也需要使用volatile么?  这样的话,对我的打击也太大了点.

我以前可是经常在一个线程通过设置一个全局变量通知另外一个 ...


看着都着急, 你这么想就明白了.
编译器在进行对源码编译过程中,通常会对反复使用的变量整个逼本到reg当中从而提高访问速度.由volatile声明的变量,实际上就是通知编译器该变量会以你意想不到的方式被更改,所以你丫别优化我. 那么编译器意想不到的方式有哪几种呢,如下:
1.Memory map的硬件寄存器(比如). 状态寄存器是最常见, 你想呀, 硬件修改这变量他会告诉编译器嘛, 不会也没这能力, 那编译器不就傻呵呵的把该变量优化了嘛, 一优化就坏事了, 因为我们读到的都是reg中存储的旧的状态寄存器的值, 而非memory当中最新的状态寄存器值. 抄个定义给你看看: #define rIICSTAT (*(volatile unsigned *)0x54000004) //IIC status

2.多线程中被几个线程共享的变量. 线程修改共享变量var会通知编译器嘛,不会也没这能力,所以线程A使劲读着var在reg中的副本(狗日的编译器优化),读出来1时他好大展鸿图呀,结果读出来的都是0, 而线程B早就把var变量给修改为1了,怪谁呀,只怪没加volatile,加上volatile不早就读memory当中的var新值1了嘛.

3.ISR当中用.这个麻烦,需要拿程序举例,俺就不写了.

再有, 讨论volatile就讨论volatile. 跟cache有嘛关系, cache是不可见的...不可见的...我看不着~~~

论坛徽章:
0
75 [报告]
发表于 2008-03-07 11:17 |只看该作者
原帖由 飞雪横天 于 2008-3-7 10:43 发表



您的意思是说, 有的编译器可能给优化掉了, 有的编译器就不优化了, 那就是说我们这种设计最好是加上volatile了?

我基本上在这种情况下,没有见过通知线程退出的变量,需要用volatile


是的。为了避免以后因为在不同编译器或在不同版本的同一编译器编译而带来的麻烦,建议应该这样做。除非你确定以后不换编译器编译这个程序。

论坛徽章:
0
76 [报告]
发表于 2008-03-07 11:49 |只看该作者
这里有一个gcc-volatile的讨论http://gcc.gnu.org/ml/gcc/2007-10/msg00266.html


>   If you really want all externally-visible accesses to v to be made exactly
> as the code directs, rather than allowing gcc to optimise them in any way that
> (from the program's POV) it's just the same 'as-if' they had been done
> exactly, make v volatile.

That is not enough. Apart from the lack of ISO semantics for volatile,
typically a compiler will take volatile as a hint to not hold
values of the variable in a register.

On a multi-processor, this is not enough, because each CPU
may still hold modified values in separate caches.

Perhaps gcc actually puts a RW barrier to force
cache synchronisation on every volatile access..
this seems rather expensive and very hard to do since
it is very dependent on the actual box (not just the
processor). Some processor caches might require external
electrical signals to synchronise, for example. This is
quite possible if you have multiple CPU boards in a box.

But I don't actually know what gcc does, although I guess
it does nothing. The OS has to do the right thing here
when a mutex is locked etc, but the code for that is
probably in the kernel which is better able to manage
things like cache synchronisation than a compiler.

c/c++没有多线程的概念,没有一个明确的memory model,volatile不能保证共享变量在多线称间同步,
应该使用明确的lock。

论坛徽章:
0
77 [报告]
发表于 2008-03-09 15:41 |只看该作者
原帖由 zx_wing 于 2008-2-29 14:20 发表

他骗你的。
volatie变量和cache没有关系,只和内存有关系。
简单点说就是每次操作前从内存取值
有volatie修饰的变量,每次操作时遵循下面动作:
从内存取值 ---> 放入寄存器 ----> 操作 ---->写回内存
没 ...

留个位置,呵呵

论坛徽章:
0
78 [报告]
发表于 2008-03-19 21:39 |只看该作者
顶上来顶上来

论坛徽章:
0
79 [报告]
发表于 2008-03-20 19:01 |只看该作者
volatie变量和cache没有关系,只和内存有关系。
简单点说就是每次操作前从内存取值
有volatie修饰的变量,每次操作时遵循下面动作:
从内存取值 ---> 放入寄存器 ----> 操作 ---->写回内存

楼上的回答很清楚

论坛徽章:
0
80 [报告]
发表于 2008-03-20 20:05 |只看该作者
原帖由 zx_wing 于 2008-2-29 14:20 发表

他骗你的。
volatie变量和cache没有关系,只和内存有关系。
简单点说就是每次操作前从内存取值
有volatie修饰的变量,每次操作时遵循下面动作:
从内存取值 ---> 放入寄存器 ----> 操作 ---->写回内存
没 ...



我有一个问题想请教, 就是在多线程中, 有一个全局变量没有用volatile去修饰, 而我只是用锁去进行互斥地访问.
那么假如我线程1在执行时将这个变量放到了cache中, 有没有这种可能: 也就是在放弃锁的时候这个变量仍然没有被写回内存,那么我另外一个线程从内存中读的话就不会读到最新的值了.
想请教一下会不会有这种可能. 谢谢.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP