单核多核加锁互斥问题

积少@成多 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?

...全文
1672 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
meepyou 2018-08-03
  • 打赏
  • 举报
回复
没仔细看,但好像记得子线程创建时会从主线程中继承一些环境过来,而且可能会比主线程更早执行后续部分代码(有一定随机性),因此在线程创建后加一个ulseep(1)之类的看看。
yyfhz 2018-05-15
  • 打赏
  • 举报
回复
线程是相互隔离的,寄存器的内容并不能在线程之间通用,线程切换包含寄存器的状态压栈和目标线程状态的恢复。所以不加锁的话会发生冲突。
噼里啪啦222 2017-11-22
  • 打赏
  • 举报
回复
问题1: 这里应该不是缓存的问题,是原子性的问题,global ++;实际是多条指令,大概可能是这样: count++不是原子操作,是3个原子操作组合 1.读取主存中的count值,赋值给一个局部成员变量tmp 2.tmp+1 3.将tmp赋值给count 可能会出现线程1运行到第2步的时候,tmp值为1;这时CPU调度切换到线程2执行完毕,count值为1;切换到线程1,继续执行第3步,count被赋值为1------------结果就是两个线程执行完毕,count的值只加了1; 加锁是解决原子、可视、有序三个问题,不是就一个可视问题。 问题2: 大概就是你说的那样,需要注意一点,加锁的原理的是在进入锁之前和退出锁之后,同步一次缓存和内存中的数据。这么理解就明白了吧。 这个问题我也没完全懂,再深入就不懂了,欢迎大佬指正
jixushashade 2017-05-05
  • 打赏
  • 举报
回复
应该是线程循环的次数太少,才2000次 用不了一个时间片就能处理完所以基本不会出现不等于4000的情况。 多核这部分没涉及过 所以不太清楚,而且很有可能也是因为执行时间太短造成。

2,408

社区成员

发帖
与我相关
我的任务
社区描述
高性能计算
社区管理员
  • 高性能计算社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧