OS - 一文带你快速精通程序、进程、线程、纤程

以下本文都是在OS角度说的。

面试高频:进程和线程有什么区别?

  • 非专业回答:进程就是一个程序运行起来的状态,线程是一个进程中的不同的执行路径
    专业回答:进程是OS分配资源的基本单位,线程是执行调度的基本单位
    分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己独立的内存空间)

  • 纤程:用户态的线程,线程中的线程,切换和调度不需要经过OS
    优势:1:占有资源很少 OS : 线程1M Fiber:4K 2:切换比较简单 3:启动很多个10W+
    截止本文发布时支持内置纤程的语言:Kotlin Scala Go Python(lib)... Java? (open jdk : loom)

JAVA中对纤程的支持:目前没内置,期望内置

利用Quaser库(不成熟)



co.paralleluniverse
quasar-core
0.8.0

// 线程版本:
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.SuspendableRunnable;
public class HelloFiber {
    public static void main(String[] args) throws  Exception {
        long start = System.currentTimeMillis();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                calc();
            }
        };
        int size = 10000;
        Thread[] threads = new Thread[size];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(r);
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].start();
        }
        for (int i = 0; i < threads.length; i++) {
            threads[i].join();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
    static void calc() {
        int result = 0;
        for (int m = 0; m < 10000; m++) {
            for (int i = 0; i < 200; i++) result += i;
        }
    }
}
// 大概耗时7s
// 纤程版本
import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.SuspendableRunnable;
public class HelloFiber2 {
    public static void main(String[] args) throws  Exception {
        long start = System.currentTimeMillis();
        int size = 10000;
        Fiber[] fibers = new Fiber[size];
        for (int i = 0; i < fibers.length; i++) {
            fibers[i] = new Fiber(new SuspendableRunnable() {
                public void run() throws SuspendExecution, InterruptedException {
                    calc();
                }
            });
        }
        for (int i = 0; i < fibers.length; i++) {
            fibers[i].start();
        }
        for (int i = 0; i < fibers.length; i++) {
            fibers[i].join();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
    static void calc() {
        int result = 0;
        for (int m = 0; m < 10000; m++) {
            for (int i = 0; i < 200; i++) result += i;
        }
    }
}
// 大概耗时3秒,纤程之间的切换很轻盈,是在用户态内部进行的,不需要os参与

大家可以尝试:目前是10000个Fiber -> 1个JVM线程,想办法提高效率,10000Fiber -> 10份 -> 10Threads

纤程的使用的场景

纤程 vs 线程池:很短的计算任务,不需要和内核打交道,并发量高!

进程创建和启动

fork and exec.png

linux是c语言写的,它对外提供一些类库和接口,比如fork(),创建进程调用系统的函数fork() 产生一个子进程,其实内部还是clone方式产生的,即从父进程克隆出一个

僵尸进程 & 孤儿进程

  • 僵尸进程:父进程产生子进程之后,会维护子进程的一个PCB结构,如果子进程退出了,由父进程释放;如果父进程没有释放,那么子进程成为一个僵尸进程。
  • 孤儿进程:子进程结束之前,父进程已经退出
    孤儿进程会成为init进程的孩子,由1号进程维护

进程调度(了解)

Linux 2.6采用CFS调度策略:Completely Fair Scheduler
按优先级分配时间片的比例,记录每个进程的执行时间,,如果有一个进程执行时间不到他应该分配的比例,优先执行。
默认调度策略:
实时优先级分高低 : FIFO (First In First Out),
优先级一样 : RR(Round Robin)
普通: CFS

  • 多任务
    -- 非抢占式:除非进程主动让出cpu,否则一直运行
    -- 抢占式:由进程调度器强制开启或暂停某一进城的执行

————————————————————
坐标帝都,白天上班族,晚上是知识的分享者
如果读完觉得有收获的话,欢迎点赞加关注

你可能感兴趣的:(OS - 一文带你快速精通程序、进程、线程、纤程)