单核多核加锁互斥问题
积少@成多 2017-03-05 10:50:08 源码
#include <stdio.h>
#include <pthread.h>
int global;
void *thread(void *st){
int i;
for (i = 0; i < 2000; i++)
{
global ++;
}
}
int main(int argc, char **argv)
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thread,NULL);
pthread_create(&tid2,NULL,thread,NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d \n", global);
return 0;
}
问题:在thread函数中如果加锁,结果等于4000,否则小于4000。 无论是单核还是多核环境都验证过。
这种问题一般人看一眼就会回答你写错了,没加锁啊。我也知道这样写不对,但具体原因还是有一些疑惑,希望大神们给予解答。
问题1:单核环境为啥加锁?
单核环境示意图
core-register L1cache L2cache RAM
单核CPU,所有线程共用一套寄存器,cache与RAM。当线程1在执行global ++操作时,会把global最新的值写入L1cache,是否时刻写入L2cache我不太清楚,这个时候线程切换到线程2,寄存器也都会被线程2所用,线程2会从L1 cache中将数据读到寄存器去执行,这样的话不加锁理论是也是没问题的,但实际效果来看,还是必须要加锁。
问题2: 多核环境为啥加锁?
多核环境示意图
core1-register L1cache
L2cache RAM
core2-register L1cache
多核CPU,每个核有自己的一套寄存器,L1cache是独立的, L2cache与RAM是共享的。
线程1在core1上执行,线程2在core2上执行。假设2个核的L1 cache都有global这个条目。
当线程1在执行global ++操作时,会把global最新的值写入core1的L1cache,是否时刻写入L2cache我不太清楚,即使写入了L2 cache,core2的 L1 cache会知道吗?这个时候线程切换到线程2,线程2会从core2的 L1 cache 中将数据读到寄存器去执行,这样极可能造成不同步,但是加锁为什么又能解决了呢,难道加锁之后 core1会在写cache的时候会把数据同步到 core2的 L1 cache?