多核、多线程、并发与并行

一、概念

  • 进程与线程
    进程是操作系统进行资源分配管理和调度的单元,比如我们打开QQ,运行的QQ就是一个进程。
    线程是进程的一个子集,线程是CPU进行调度和执行的单元。
    一个进程可以包含一个线程(单线程的进程),也可以包含多个线程(多线程的进程)。
  • 多核与多线程
    在单核时代,也可以实现多线程,同一时间内,各个(同一或者不同)线程争夺CPU时间片。
    在多核时代,各个进程及其线程可以在不同CPU内核上执行。多核为多线程并行执行提供了可能。
  • 并发、并行与串行
    串行:各个线程排队等待CPU的执行。
    并发:指的是不同线程同时争夺一个CPU内核的时间片,这种状态就是并发。
    在这里插入图片描述
    并行:不同线程在不同CPU内核上同时执行,彼此相互不影响。
    在这里插入图片描述

二、效率与时间

我们通常说并发能够提升执行效率,觉得并发就跟提升效率有关。
现在假设有一种情况,一个多线程的进程,在被分配在固定的CPU内核上执行,各个线程虽然在并发,但是CPU一会执行这个线程,一会儿执行那个线程,不断切换,这个跟CPU先执行完A线程的任务,再执行完B线程的任务,接着C线程的任务…并没有什么时间效率上的提升,更有甚者,CPU在不断切换线程时,也需要不断切换线程上下文,切换上下文会带来时间和资源开销,与其这样并发,还不如串行呢?
所以,这里有个理解误区,提升效率不等于缩短执行时间。
假使打开QQ,我们一边时而回复聊天,时而逛空间,如果,采用串行的方式,我们就得等聊天完成后,才能正常逛空间;而如果采用多线程的方式,CPU不断切换线程执行,宏观上我们就会觉得聊天和逛空间完全可以同时进行。这就是提升了效率。
另一点理解误区,并发能缩短总执行时间。
一个多线程的进程运行在多核CPU上,它到底是并行还是并发,这个我不知道,因为CPU调度一会儿把线程分配在这个CPU内核上,一会儿把CPU分配在那个CPU内核上,各个线程可能在同一CPU内核,也可能在不同CPU内核。当在不同的CPU内核执行时,这两个线程就是并行;当两个CPU内核同时争夺同一个CPU内核的时间片时,这两个线程就是并发。
而并行才能缩短总的执行时间。

三、多线程的进程不一定会使用多核并行处理

验证如下:
本机电脑4核8G。
如下案例,开启4个线程每个线程依次打印100万次。

package org.example.demo5;

public class ThreadTest {

    private static final int num = 1000 * 1000;

    public static void main(String[] args) throws InterruptedException {
        //因为Visual VM找到java进程需要时间,所以这里让主线程先睡一会儿,
        //等待Visual VM找到进程再开始启动各子进程打印
        Thread.sleep(50000); 

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }

        },"线程1").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }

        },"线程2").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }
        },"线程3").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }
        },"线程4").start();

    }
}

通过使用Visual VM查看线程状态,可知各个线程是在同一个CPU上并发执行的。
图片
修改执行次数,改成2000万次

package org.example.demo5;

public class ThreadTest {

    private static final int num = 20000 * 1000;

    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(50000);

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }

        },"线程1").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }

        },"线程2").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }
        },"线程3").start();

        new Thread(()->{
            for (int i = 0; i < num; i++) {
                System.out.println(i);
            }
        },"线程4").start();

    }
}

通过下图可知,4个线程同时存在并发核并行的情况。
在这里插入图片描述

根据以上案例可知:
一个多线程的进程在多核处理器上,可能是以并发的方式运行,也可能是以并发+并行的方式运行。

参考:

https://www.cnblogs.com/jiading/articles/12454398.html
https://blog.csdn.net/qq_33290787/article/details/51790605
Visual VM工具的使用
https://www.cnblogs.com/xifengxiaoma/p/9402497.html

  • 3
    点赞
  • 12
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

持续成长

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值