僵尸线程产生原因? golang线程池原理?

bdqnwqk2024-08-06问题1

一、僵尸线程产生原因?

僵尸进程的产生:

当一个进程创建了一个子进程时,他们的运行时异步的。即父进程无法预知子进程会在什么时候结束,那么如果父进程很繁忙来不及wait 子进程时,那么当子进程结束时,会不会丢失子进程的结束时的状态信息呢?处于这种考虑unix提供了一种机制可以保证只要父进程想知道子进程结束时的信息,它就可以得到。

这种机制是:在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存。但是仍然保留了一些信息(如进程号pid 退出状态 运行时间等)。这些保留的信息直到进程通过调用wait/waitpid时才会释放。这样就导致了一个问题,如果没有调用wait/waitpid的话,那么保留的信息就不会释放。比如进程号就会被一直占用了。但系统所能使用的进程号的有限的,如果产生大量的僵尸进程,将导致系统没有可用的进程号而导致系统不能创建进程。所以我们应该避免僵尸进程

这里有一个需要注意的地方。如果子进程先结束而父进程后结束,即子进程结束后,父进程还在继续运行但是并未调用wait/waitpid那子进程就会成为僵尸进程。

但如果子进程后结束,即父进程先结束了,但没有调用wait/waitpid来等待子进程的结束,此时子进程还在运行,父进程已经结束。那么并不会产生僵尸进程。应为每个进程结束时,系统都会扫描当前系统中运行的所有进程,看看有没有哪个进程时刚刚结束的这个进程的子进程,如果有,就有init来接管它,成为它的父进程。

同样的在产生僵尸进程的那种情况下,即子进程结束了但父进程还在继续运行(并未调用wait/waitpid)这段期间,假如父进程异常终止了,那么该子进程就会自动被init接管。那么它就不再是僵尸进程了。应为intit会发现并释放它所占有的资源。(当然如果进程表越大,init发现它接管僵尸进程这个过程就会变得越慢,所以在init为发现他们之前,僵尸进程依旧消耗着系统的资源)

二、golang线程池原理?

golang线程池属于对象池.所有对象池都具有一个非常重要的共性,就是为了最大程度复用对象.那么线程池的最

  重要的特征也就是最大程度利用线程.

  首先,创建线程本身需要额外(相对于执行任务而必须的资源)的开销.

  作业系统在每创建一个线程时,至少需要创建以下资源:

  (1) 线程内核对象:用于对线程上下文的管理.

  (2) 用户模式执行栈.

  (3) 内核模式执行栈.

  这些资源被线程占有后作业系统和用户都无法使用.

  相反的过程,销毁线程需要回收资源,也需要一定开销.

  其次,过多的线程将导致过度的切换.线程切换带来的性能更是不可估量.系统完成线程切换要经过以下过程:

  (1) 从用户模式切换到内核模式.

  (2) 将cpu寄存器的值保存到当前线程的内核对象中.

  (3)打开一个自旋锁,根据调度策略决定下一个要执行的线程.释放自旋锁,如果要执行的线程不是同一进

  程中的线程,还需要切换虚拟内存等进程环境.

  (4) 将要执行的线程的内核对象的值写到cpu寄存器中.

  (5) 切换到用户模式执行新线程的执行逻辑.

  所以线程池的目的就是为了减少创建和切换线程的额外开销,利用已经的线程多次循环执行多个任务从而提

  高系统的处理能力.

三、线程池shutdown原理?

当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。

四、concurrenthashmap线程安全的原理?

在ConcurrentHashMap没有出现以前,jdk使用hashtable来实现线程安全,但是hashtable是将整个hash表锁住,所以效率很低下。

ConcurrentHashMap将数据分别放到多个Segment中,默认16个,每一个Segment中又包含了多个HashEntry列表数组,

对于一个key,需要经过三次hash操作,才能最终定位这个元素的位置,这三次hash分别为:

对于一个key,先进行一次hash操作,得到hash值h1,也即h1 = hash1(key);

将得到的h1的高几位进行第二次hash,得到hash值h2,也即h2 = hash2(h1高几位),通过h2能够确定

五、固定线程池工作原理?

固定线程池的工作原理是固定线存值打开一个缺口将外围的水放进来。

六、多线程join的原理?

join的原理就是调用相应线程的wait方法进行等待操作,从而达到同步的目的。

七、线程等待唤醒机制原理?

void wait () 在其他线程调用此对象的 notify () 方法或 notifyAll () 方法前,导致当前线程等待。

void wait (long timeout) 在其他线程调用此对象的 notify () 方法或 notifyAll () 方法,或者超过指定的时间量前,导致当前线程等待。

void notify () 唤醒在此对象监视器上等待的单个线程

void notifyAll () 唤醒在此对象监视器上等待的所有线程。

八、jdk自带线程池有哪些,线程join的原理?

newFixedThreadPool创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

九、多线程的wait实现原理?

该多线程的wait实现原理如下:

wait()方法是Object 类的方法,它的作用是使当前执行wait()方法的线程等待,在wait()所在的代码行处暂停执行,并释放锁,直到接到通知或中断。

十、dubbo线程池原理及源码?

DUBBO提供五种线程模型

all 所有消息都派发到业务线程池,包括请求,响应,连接事件,断开事件,心跳

direct 所有消息都不派发到业务线程池,全部在IO线程直接执行

message 只有请求响应消息派发到业务线程池,其它连接断开事件,心跳等消息直接在IO线程执行

execution 只有请求消息派发到业务线程池,响应和其它连接断开事件,心跳等消息直接在IO线程执行

connection 在IO线程上将连接断开事件放入队列,有序逐个执行,其它消息派发到业务线程池