什么是线程
简述:
线程是操作系统能够进行调度的最小单位。它运行于进程中。进程将资源整合在一起,以供线程使用。
为什么要有线程
创建线程的开销远小于进程
进程和线程的区别
1. 线程共享创建它的进程的地址空间;过程有它们自己的。地址空间
2. 线程可以直接访问其进程的数据;进程有自己的父进程数据段的副本。
3.线程可以直接与进程中的其他线程通信;进程必须使用进程间通信来与同级进程通信
4. 新线程很容易创建;新的进程需要父进程的复制。
5. 线程可以对同一进程的线程进行相当大的控制;流程只能对子流程进行控制。6. 主线程的更改(取消、优先级更改等)可能会影响进程中其他线程的行为;对父进程的更改不会影响子进程。
不同进程间是充满敌意的,彼此是抢占,竞争cpu的关系;例如:酷狗会和mysql抢占资源。
不同线程之间是数据共享的是合作关系,一个线程可以访问另外一个线程的内存地址
为何要用多线程(线程对比进程的好处)
1.多线程共享一个进程的地址空间。线程之间数据共享
2.线程比进程更轻量级,线程比进程更容易创建并且可以撤销。创建线程耗时是进程的十分之一到百分之一
3.如果使用多线程是cpu密集型的,那么不能获得性能上的增加,但是如果线程处理大量I/O操作,多线程可以节约时间,加快程序执行的速度
4.在多cpu的系统中(现在电脑多为多cpu),为了最大限度利用多核,可以开启多个线程并且比进程开销小很多(cpython不适用,GIL锁)
线程的问题
线程通常是有益的,但是带来了不小程序设计难度,线程的问题是:
1. 父进程有多个线程,那么开启的子线程是否需要同样多的线程
如果是,那么附近中某个线程被阻塞,那么copy到子进程后,copy版的线程也要被阻塞吗,想一想nginx的多线程模式接收用户连接。
2. 在同一个进程中,如果一个线程关闭了问题,而另外一个线程正准备往该文件内写内容呢?
如果一个线程注意到没有内存了,并开始分配更多的内存,在工作一半时,发生线程切换,新的线程也发现内存不够用了,又开始分配更多的内存,这样内存就被分配了多次,这些问题都是多线程编程的典型问题,需要仔细思考和设计。
使用线程池如何设计IO密集型多线程和CPU密集型多线程
首先线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。
正是因为线程池的这些特点,当我们需要初始化一个线程池时,就要考虑我们的线程池被用来执行什么样的任务。
常见的任务分为两种:CPU密集型任务和IO密集型任务
CPU密集型任务(CPU-bound):在一个任务中,主要做计算,CPU持续在运行,CPU利用率高,具有这种特点的任务称为CPU密集型任务。
IO密集型任务(IO-bound):在一个任务中,大部分时间在进行I/O操作,由于I/O速度远远小于CPU,所以任务的大部分时间都在等待IO,CPU利用率低,具有这种特点的任务称为IO密集型任务。
所以我们在设计线程池时,应先对执行的任务有个大体分类,然后根据类型进行设置。一般而言,两种任务的线程数设置如下:
CPU密集型任务:线程个数为CPU核数。这几个线程可以并行执行,不存在线程切换到开销,提高了cpu的利用率的同时也减少了切换线程导致的性能损耗
IO密集型:线程个数为CPU核数的两倍。到其中的线程在IO操作的时候,其他线程可以继续用cpu,提高了cpu的利用率