zoukankan      html  css  js  c++  java
  • 浅谈并发并行异步同步

    引言:

    最近一直对于并行异步同步的问题存在疑惑,网上只有笼统的解释,并不能很好的解决疑惑,所以写了下自己的一些认识,欢迎大家拍砖。

    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
    ", 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
    ", 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
    ", 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

    转载请注明地址:http://www.cnblogs.com/handsomecui/

  • 相关阅读:
    会场安排
    Comet OJ
    CodeForces1154F
    CodeForces1154E
    2019.08.25校内模拟赛Graph
    2019.08.25校内模拟赛Page
    [MtOI2019]灵梦的计算器
    [MtOI2019]永夜的报应
    [NOI2018]归程
    USACO[CowCoupons]
  • 原文地址:https://www.cnblogs.com/handsomecui/p/5780904.html
Copyright © 2011-2022 走看看