打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
同步 异步 多线程 单核 多核 并行的区别(转)

同步 异步 多线程 单核 多核 并行的区别

我认为大家将异步的概念 和多线程混淆在一起了

举个简单的例子,  假设我要做 烧开水,举杠铃100下, 洗衣服 3件事情。

烧开水 这件事情,  我要做的事情为, 准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
举杠铃100下        我要做的事情为,  举杠铃100下  10分钟
洗衣服            我要做的事情为, 准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟


单核情况下
同步的完成,我需要做的时间为 1+ 8 +1 + 10 + 1+ 5 +1 = 27 分

如果异步,就是在等的时候,我可以切换去做别的事情

准备烧开水(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分钟

 

 

多线程的做法
单核下

线程1  准备烧开水 1分钟, 等开水烧开 8 分钟 , 关掉烧水机 1分钟
线程2  举杠铃100下  10分钟
线程3  准备洗衣服 1分钟, 等开水烧开 5 分钟 , 关掉洗衣机 1分钟

cpu 可能这么切换 最理想的切换方式

线程1  准备烧开水1  sleep  1          sleep 5            sleep 1          sleep 2          关开水 1分钟 exit
线程2    sleep 1      sleep  1            举杠铃50 5分钟    sleep 1          举杠铃20 2分钟  sleep1      举杠铃30下 3分钟       
线程3    sleep  1      准备洗衣服1 分钟    sleep 5            关洗衣机1分钟    exit


最后使用了  14分钟  和异步是一样的。
但是实际上是不一样的,因为线程不会按照我们设想的去跑, 如果线程2 举杠铃先跑,整个流程的速度就下来了。


异步和同步的区别,  在io等待的时候,同步不会切走,浪费了时间。

如果都是独占cpu 的业务, 比如举杠铃的业务, 在单核情况下 多线和单线 没有区别。

多线程的好处,比较容易的实现了 异步切换的思想, 因为异步的程序很难写的。多线程本身程还是以同步完成,但是应该说
比效率是比不上异步的。 而且多线很容易写, 相对效率也高。


多核的好处,就是可以同时做事情, 这个和单核完全不一样的。


至于多核运行 这3个线程的情况 就留给你们自己完成了。

 

 

多线程本身的流程大多数是按照同步方式来完成,因为cpu可以将线程切走,可以比较好的利用cpu
如果是单线同步,效率就会低很多。

单核心下 多线程提高的地方,大多数情况下 我认为可以简单的认为就是io的时候,cpu 切到另一个线程,提高了效率。 而切换的代价忽略不计。

如果线程本身很多,那么它切换的代价就很大。这个和操作系统的进程切换是一个概念。

线程切换的 原理和 os 的进程切换 我感觉很相似。os 的进程切换也有代价, 操作系统
里面也学过了,如果全是cpu 计算,分时操作系统不能提高速度,只会降低速度.多线程也一样。

以网络操作为例
如果用全异步做,速度无疑更快。 这点上 steven 在他的upn 里面已经证明了
但是他同时也说考虑到异步代码的复杂和难写,多线程是很好的选择。


个人认为epoll iocp 的出现,其实就是 对多线程+ 同步做法的改进, 改成了多线程 +异步提醒。
因为网络的速度比cpu慢很多,多线程+ 同步 cpu 空等太多了。(一家之言)

 

 

 

下面2个多线程的代码, 分别可以看作是io 操作 和重cpu 计算的例子。

它们在单核和多核  下面的显示出来的效果是不一致的,可以帮你更好的了解 什么是多核, 什么是单核

多线程的意义。

 

// 类似io 操作, 多线程运行, cpu 切走,可以提高运行速度。

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//using namespace std;

DWORD WINAPI fun1(void *);
DWORD WINAPI fun2(void *);

int main()
{

fprintf(stderr, " begin %d\n", (unsigned int)time(NULL));
HANDLE h1 = CreateThread(NULL, NULL, fun1,NULL,NULL,NULL);
HANDLE h2 = CreateThread(NULL, NULL, fun2,NULL,NULL,NULL);

::WaitForSingleObject(h2, INFINITE);
::WaitForSingleObject(h1, INFINITE);
fprintf(stderr, " end %d\n", (unsigned int)time(NULL));

CloseHandle(h1);
CloseHandle(h2);
return 0;
}

DWORD WINAPI fun1(void *)
{
fprintf(stderr, " thread1 begin %d\n", (unsigned int)time(NULL));
::Sleep(1000 *10);
fprintf(stderr, " thread1 end %d\n", (unsigned int)time(NULL));
return 0;


}

DWORD WINAPI fun2(void *)
{
fprintf(stderr, " thread2 begin %d\n", (unsigned int)time(NULL));
::Sleep(1000 *5);
fprintf(stderr, " thread2 end %d\n", (unsigned int)time(NULL));
return 0;
}

 

//// 

代码 2 重cpu计算, 单核无法提高效率,多核可以提高效率

 

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//using namespace std;

DWORD WINAPI fun1(void *);
DWORD WINAPI fun2(void *);

volicate float x[1000][1000] = {0};
float y[1000][1000] = {0};
float z[1000][1000] = {0};

void funtime(float *);

int main(int argc, char *argv)
{

fprintf(stderr, " funtime z %d\n", (unsigned int)time(NULL));
funtime(&(z[0][0]));
fprintf(stderr, " funtime z %d\n", (unsigned int)time(NULL));

fprintf(stderr, " begin %d\n", (unsigned int)time(NULL));
HANDLE h1 = CreateThread(NULL, NULL, fun1,NULL,NULL,NULL);
HANDLE h2 = CreateThread(NULL, NULL, fun2,NULL,NULL,NULL);

::WaitForSingleObject(h2, INFINITE);
::WaitForSingleObject(h1, INFINITE);
fprintf(stderr, " end %d\n", (unsigned int)time(NULL));

CloseHandle(h1);
CloseHandle(h2);
getchar();

return 0;
}

DWORD WINAPI fun1(void *)
{
fprintf(stderr, " thread1 begin %d\n", (unsigned int)time(NULL));
funtime(&(x[0][0]));
::Sleep(1000 *10);
fprintf(stderr, " thread1 end %d\n", (unsigned int)time(NULL));
return 0;
}

DWORD WINAPI fun2(void *)
{
fprintf(stderr, " thread2 begin %d\n", (unsigned int)time(NULL));
funtime(&(y[0][0]));
::Sleep(1000 *5);
fprintf(stderr, " thread2 end %d\n", (unsigned int)time(NULL));
return 0;
}

void funtime(float *table)
{
unsigned int t = time(NULL);
float PI = 3.14156925354;
for (int k =0; k < 100;k++)
for (int x = 0; x < 1000; ++x)
for (int y = 0; y < 1000; ++y) {
*(table +x*1000+ y) = PI *(t+x)*(t+y);
t++;
}
}

多核下的速度提升倍数要小于核的数量,因为会访问一些共享资源,或者有IO操作,cache共享等 的看法

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
[FFMPEG-2]最想实现的第一点一个功能-从mp3中提取pcm数据,重采样和加wav头
Bloom filter (C) - LiteratePrograms
base64编码、解码的C语言实现
Linux用户态控制GPIO
Android显示yuv数据
一个将文件数据(汉字)导入到mysql的C程序_原创文档_论坛_PHPChina 开源社区...
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服