线程
1.概念:进程内部的一条执行路径或执行序列;(线程是进程的一个实体)
2.实现方式:a.用户线程:创建 销毁 管理由线程库完成,无法使用多线程处理器的好处;
b.内核级线程:创建 销毁 管理由内核完成,创建代价高,但可以使用多线程处理器的好处;
3. 线程同步
互斥锁 条件变量 信号量
(1)互斥锁
用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他线程才可以开始利用这个资源
I.互斥锁的实现
互斥锁的实现和我们现实生活中打印机的使用情况特别类似。如果有一台打印机,A正在打印东西,但是还没有打印完,B又想使用打印机,如果此时打印机不做任何事情的话打印出来的东西必定是乱的。因此,必须要对打印机做一个处理,我在打印东西的时候别人是不允许打印的,只有我用完别人才能使用。这个过程有点类似于,我将打印机放在一个房间里面,给门上放一把锁,这个锁是默认打开的,当我进去的时候会将锁锁住,然后下一个人来打印东西时,首先要检查这个锁,如果是锁住的,那么他只能在门外等,直到我在里面打开锁。这个整体的过程就和我们互斥锁的实现特别相似。
(2)信号量
以一个停车场的运行为例。假设一个停车场只有三个车位,一开始三个车位都是空的,这时候来了5辆车,看门人只允许其中三辆进入,然后放下车栏,剩下的2辆只能在外面等着,此后,如果有来的车辆也在外面等着。这时,有一辆车离开,看门人就可以放入外面的一辆车进去,接下来如果再有两辆离开,看门人又可以放入两辆车进去,如此反复。
在上例当中,车位属于公共资源,每个车辆相当于一个线程,看门人就是信号量。
I.信号量的特性
信号量是一个非负整数,所有通过它的线程都会将该整数减一(通过它是为了使用资源),当该整数值为0时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作:wait(等待) 和release(释放)。当一个线程调用wait操作时,它要么得到资源然后将信号量减一,要么一直等待下去,直到信号量大于等于一时。Release实际上是在信号量上执行加操作,对应于车辆离开停车场
*临界资源:一次仅允许一个进程使用的资源(这里的资源可以是软硬件设备)
*临界区:访问临界资源的代码段;
(3)信号量与互斥锁的区别
I.作用域:信号量:进程或线程间;
互斥锁:线程间;
II.上锁时:信号量:只要信号量的值大于0,其它线程就可以被sem_wait成功,成功后,信号量的值减一;如果信号量的值小于0,则sem_wait阻塞,直到sem_post释放后,信号量的值加1.
互斥锁:只要被锁住,其它线程都不可以访问B被保护的资源。如果没有锁,获取资源成功,否则进行等待资源可用。
4. 线程安全
(1)概念及原理
多个线程访问同一个代码,不会产生不确定的结果。编写线程安全的代码是要依靠线程同步来完成的。
5.线程之间是如何进行通信的?
一个是使用全局变量进行通信,还有就是可以使用自定义的消息机制传递信息。其实,因为各个线程之间它是共享进程资源的,所以它没有像进程中的用于数据交换的通信方式,它通信的主要目的在于线程同步。
6.C++中多线程实现的几种方式
(1)直接使用WIN32 API Create Thread
(2)用C运行库_beginthread创建线程
(3)运用第三方线程库,比如boost的thread等;
_beginthread和Create Thread的区别:_beginthered内部调用了Create Thread.
如果程序只调用Win32 API,就放心用Create Thread,如果要用到C++运行库,那么就使用_beginthread,因为C++运行库有一些函数里面使用了全局变量,beginthread为这些全局变量做了处理,使得每个线程都有一份独立的“全局”量,在这种情况下使用Create Thread的话就会出现不安全的问题;
7.多线程中栈与堆是公有的还是私有的?
因为线程是共享进程的资源,所以栈是私有的,堆是公有的。
8.线程池
线程池就是一堆已经建立好的线程,最大数目一定,然后初始后都处于空闲状态,当有新任务到来时就取出空闲线程处理任务,任务完成之后又重新放回去,当线程池中的所有线程都在任务时,只能等待有线程结束任务才能执行;