浅谈并发并行异步同步
引言:
最近一直对于并行异步同步的问题存在疑惑,网上只有笼统的解释,并不能很好的解决疑惑,所以写了下自己的一些认识,欢迎大家拍砖。
1.关键字的解释:
并行: 一般指并行计算,是说同一时刻有多条指令同时被执行,这些指令可能执行于同一CPU的多核上,或者多个CPU上,或者多个物理主机甚至多个网络中.
其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。
异步:与同步相对应,异步指的是让CPU暂时搁置当前请求的响应,处理下一个请求,当通过轮询或其他方式得到回调通知后,开始运行。多线程将异步操作放入另一线程中运行,通过轮询或回调方法得到完成通知,但是完成端口,由操作系统接管异步操作的调度,通过硬件中断,在完成时触发回调方法,此方式不需要占用额外线程。
2.结合代码的讲解:
最好的讲解方式莫过于代码演示,针对并发:
#include <stdio.h> #include <pthread.h> //线程 /***************************************** void *fun2(void *arg){ char s[110]; while(1){ puts("你是handsomecui!"); sleep(2); } } void *fun1(void *arg){ char s[100]; while(1){ scanf("%ss", s); printf("人生自古多无情 : %s\n", s); sleep(3); } } int main(){ pthread_t pid[10]; int i; for(i = 0; i < 10; i++){ if(i & 1) pthread_create(&pid[i], NULL, fun1, NULL); else pthread_create(&pid[i], NULL, fun2, NULL); //pthread_join(pid[i], NULL); } for(i = 0; i < 10; i++){ pthread_join(pid[i], NULL); } return 0; } *************************************************************/ //进程 int main(){ int pid; pid = fork(); if(pid == 0){ while(1){ puts("我是handsomecui!"); sleep(2); } } else{ while(1){ char s[110]; scanf("%s", s); printf("人生自古多无情 : %s\n", s); sleep(3); } } return 0; }
以上通过多进程以及多线程解释了并发的概念;其实并发就是多线程或者多进程同时执行,注意进行io操作时需要加锁;
下面详细讲解并行,异步,同步的概念;
代码:
#include <stdio.h> #include <pthread.h> pthread_mutex_t mutex; void *shaoshui(void *arg){ pthread_mutex_lock(&mutex); sleep(1); puts("prepare for shaoshui!"); pthread_mutex_unlock(&mutex); sleep(8); puts("shaochui finish!"); pthread_mutex_lock(&mutex); sleep(1); puts("shut down water"); pthread_mutex_unlock(&mutex); } void *jugangling(void *arg){ pthread_mutex_lock(&mutex); sleep(10); puts("jugangling finish"); pthread_mutex_unlock(&mutex); } void *xiyifu(void *arg){ pthread_mutex_lock(&mutex); sleep(1); puts("prepare for xiyifu"); pthread_mutex_unlock(&mutex); sleep(5); puts("xiyifu finish"); pthread_mutex_lock(&mutex); sleep(1); puts("shut down xiyiji"); pthread_mutex_unlock(&mutex); } int main(){ pthread_t pth[3]; int begin = time(NULL); pthread_mutex_init(&mutex, NULL); pthread_create(&pth[0], NULL, shaoshui, NULL); pthread_create(&pth[1], NULL, xiyifu, NULL); pthread_create(&pth[2], NULL, jugangling, NULL); int i; for(i = 0; i < 3; i++){ pthread_join(pth[i], NULL); } int end = time(NULL); printf("spend time %d\n", end - begin); return 0; }
举一个简单例子, 假设我要做 烧开水,举杠铃100下, 洗衣服 3件事情。
烧开水 这件事情, 我要做的事情为, 准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
举杠铃100下 我要做的事情为, 举杠铃100下 10分钟
洗衣服 我要做的事情为, 准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟
代码思路:
线程1 准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
线程2 举杠铃100下 10分钟
线程3 准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟
单核情况下
同步的完成,我需要做的时间为 1+ 8 +1 + 10 + 1+ 5 +1 = 27 分
如果异步,就是上面的代码,需要14分钟,就是在等的时候,我们可以切换去做别的事情
准备烧开水(1) + 准备洗衣服(1) + 举50下杠铃 (5)分钟+ 关洗衣机 1分钟 + 举杠铃20下 (2)分钟+ 关烧水机 1分钟 + 举30下杠铃(3)分钟
1+1+5+1+2+1+3 =14 分钟
那么在多核的情况下,也就是说现在是多个人解决这三个问题,我们就不需要在准备洗衣服等情况下进行加锁了,你在干这件事情的时候,别的可以交给其他小伙伴:
多核 异步 并行
核1 准备烧开水 1分钟+ 举杠铃50下(5)分钟+ 等待3分钟 + 关掉烧水机 1分钟
核2 准备洗衣服 1分钟+ 举杠铃50下(5)分钟+ 关掉洗衣机 1分钟 + 等待3分钟
其实只花了 1+5+3+1 = 10分钟
其中还有双核都等待了3分钟
那么对于上面的代码我们完全可以把锁去掉,相当于多核的情况。
双核 异步 非并行
核1 举杠铃100下(10)分钟
核2 准备烧开水 1分钟+ 准备洗衣服 1分钟+ 等待5 分钟+ + 关掉烧水机 1分钟 + 等待 1 分钟 + 关掉洗衣机 1分钟
其实只花了 1+5+3+1 = 10分钟
针对并行与非并行无非就是一件事并行就是可以一起做,非并行则不然。。。
异步和同步的区别, 在io等待的时候,同步不会切走,浪费了时间。
如果都是独占cpu 的业务, 比如举杠铃的业务, 在单核情况下 多线和单线 没有区别。
多线程的好处,比较容易的实现了 异步切换的思想, 因为异步的程序很难写的。多线程本身程还是以同步完成,但是应该说
比效率是比不上异步的。 而且多线很容易写, 相对效率也高。
多核的好处,就是可以同时做事情, 这个和单核完全不一样的。
实例参考: http://blog.csdn.net/cqkxboy168/article/details/9026205