avatar

C语言-多线程程序

多线程程序在win、mac、linux中的会遇到不同的情况,其中mac和linux的程序不受影响,win可能会出现奇怪的问题。

gcc编译中需要用

1
gcc main.c -lpthread -o main

-lpthread 是 library pthead,意思是导入pthread的库

接下来我们来创建一个简单的线程

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdlib.h>
#include<pthread.h>
#include<stdio.h>
void* f1(){
printf("I'm f1\n");
return NULL;
}
int main(){
pthread_t th1;
pthread_create(&th1,NULL,f1,NULL);
return 0;
}

运行结果:

运行结果什么都没有,这是因为多线程的代码还没有执行的时候,主线程已经执行到 return 0; 主线程结束后,其他线程都会结束。

解决方法:我们只需要线程执行完在进行 return 0; 即可。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdlib.h>
#include<pthread.h>
#include<stdio.h>
void* f1(){
printf("I'm f1\n");
return NULL;
}
int main(){
pthread_t th1;
pthread_create(&th1,NULL,f1,NULL);
pthread_join(th1,NULL);
return 0;
}

运行结果:I’m f1

可见 pthread_join函数 可以使得线程执行完毕后,在执行下一条代码

下面我们来一起练习题

给你一个 int 数组,大小为10000,然后对其进行累加,输出累加结果,要求速度比遍历数组快

思路:我们可以将10000的大小分成两份,5000交给一个CPU核心处理,5000交给另一个CPU核心处理,这样理论上速度比直接遍历会提升一倍。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<stdlib.h>
#include<pthread.h>
#include<stdio.h>
int arr[10000];
typedef struct{
int Min;
int Max;
int sum;
}Data;
void* sum(void* args){
int i = 0;
Data* p_data = (Data*)args;
for(i = p_data->Min;i<p_data->Max;i++){
p_data->sum += arr[i];
}
printf("%d\n",p_data->sum);
return NULL;
}
int main(){
int i=0;
for(i = 0;i<10000;i++){
arr[i] = rand() % 50;
}
pthread_t th1;
pthread_t th2;
Data d1 = { 0 , 5000 , 0 };
Data d2 = { 5000 , 10000 , 0 };
pthread_create(&th1,NULL,sum,&d1);
pthread_create(&th2,NULL,sum,&d2);
pthread_join(th1,NULL);
pthread_join(th2,NULL);
printf("answer is %d\n",d1.sum + d2.sum);
return 0;
}

运行结果:

1
2
3
122607  
122604
answer is 245211

对于上述代码,我们可以选择拆成更多的份数,这样效率理论上来说会更好。

多线程可以提高程序的运行效率,但是可能会存在 竞态条件(race condition)

简单来说,就是多线程对于共享数据的处理由于存在一定的次序和时间差,导致最终答案与预期答案出现偏差。

比如说 i++,假设i=0,在高速并行i++的情况下,当i=100时,执行了i++,于是i=101,但是可能存在一部分线程中i=99,于是这个线程执行i++,i又变成了100,所以和预期发生的偏差

另外多线程程序中还存在一种问题就是 假共享(False Sharing),它是发生于Cache和RAM之间的读写校对延迟

Cache是单条线程中高速读写的缓存,它会将RAM某地址之后长串的数据(不管后面数据有没有用)存入缓存中,然后对其进行读写,再写回RAM中

它经常发生在数据之间很近,且为多核运算时。

解决方法:我们可以扩大共同数据之间的距离大小,或者少使用共同数据。

文章作者: 咲夜南梦
文章链接: http://yoursite.com/2019/01/20/C%E8%AF%AD%E8%A8%80-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%A8%8B%E5%BA%8F/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论