创建一个线程需要哪些资源
创建一个线程,操作系统需要为其分配一个栈空间
需要消耗cpu时间
会占用一个线程id,id有个数限制为:32768
要分配寄存器,计数器
用户模式下的方法有
原子操作(例如一个单一的全局变量),临界区。
内核模式下的方法有
事件,信号量,互斥量。
- 原子操作:指不会被线程调度机制打断的一个或一系列操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)
- 临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
- 互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问
- 信号量:允许多个线程在同一时刻去访问同一个资源。
- 事件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
锁的本质
所谓的锁,在计算机里本质上就是一块内存空间。当这个空间被赋值为1的时候表示加锁了,被赋值为0的时候表示解锁了,仅此而已。多个线程抢一个锁,就是抢着要把这块内存赋值为1。
互斥锁,自旋锁,读写锁,条件变量
互斥锁:多个线程争抢锁,拿到锁的线程执行,其余线程阻塞
自旋锁:多个线程争抢锁,拿到锁的线程执行,其余线程继续请求锁,直到获得,请求的过程会占用cpu,多出现在内核编程,有效的屏蔽中断的干扰
互斥锁,自旋锁对比
1.自旋锁通过 CPU 提供的 CAS实现,不会主动产生线程上下文切换,所以相比互斥锁来说,会快一些,开销也小一些。
2.线程没得到互斥锁会被阻塞,涉及到线程切换,需要大量的CPU指令,自旋锁没得到锁的话,会持续请求,如果长时间得不到锁的话,会占用大量cpu时间
3. 大量的线程只会短时间的持有锁的时候, 在使线程睡眠和唤醒线程上浪费大量的时间, 也许会显著降低程序的运行性能。 使用自旋锁, 线程可以充分利用调度程序分配的时间片
4.两种方案很难说哪一种更好,操作系统并不严格区分互斥锁和自旋锁,而是混合型互斥锁,在自旋一段时间后阻塞。
写锁:类似互斥锁,但允许更高的并行性,读读不冲突,读写冲突,写写冲突
条件变量:满足条件的线程执行,需要配合互斥锁来完成,条件变量本身无锁,类似于一个标志位