线程和cpu核心数关系
核心数和线程数是一比一的关系
使用了超线程技术后核心数:线程数变为 1:2的关系
CPU时间片轮转
为什么我们开发的时候允许很多线程同时跑呢?就是因为CPU时间片轮转机制,也叫RR调度。它给每个线程分配一个时间段,当它时间段结束后,它就切换到其它的线程执行,如果在时间段内就执行完,那么直接切换到其它线程,它就是通过这种线程的上下文切换,来实现多个线程同时执行。
线程和进程
- 进程。程序运行资源分配的最小单位,一个进程内部可能有多个线程,多个线程共享进程资源。
- 线程。cpu调度的最小单位,线程必须依附于进程,调用进程所分配的资源。同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈
并行和并发
- 并发。单位事件内可以同时处理事件的能力。
- 并行。同一时刻处理事件的能力。
并发编程
优点
- 充分利用cpu资源
- 加快处理请求的时间
注意事项
- 线程共享资源造成的线程安全问题
- 有可能造成死锁
- 分配过多的线程,会消耗大量资源,严重造成机器宕机。
- 线程切换造成的时间消耗
线程状态
-
死锁发生条件
- 请求保持条件
即线程p0已经占用了A资源,又请求B资源,而B资源已经被占用,于是p0必须等待,而又保持对A资源的占用
- 互斥条件
线程对资源的访问是排他性的
- 环路等待条件
即p0等待p1占用的资源,p1等待p0资源
- 不剥夺条件
线程获得资源之后,在没有结束之前,不能被其它线程剥夺。
-
活锁、死锁、饥饿锁
- 活锁
任务没有被阻塞,由于某些条件无法满足,导致一直重复尝试、失败
- 死锁
多个线程因争夺资源导致互相等待,都无法推进下去。
产生死锁的原因其实是获取锁的顺序不一致导致的。
要避免死锁发生就是要保证获取锁的顺序一致。
- 饥饿锁
一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。例如:优先度低的线程总是得不到机会执行。
-
线程调度算法
- 分时调度
所有线程轮流获取cpu使用权,平均分配时间
- 抢占调度
优先让优先级高的线程获取资源,相同则随机选一个。
-
servlet是线程安全的吗
servlet不是线程安全,不能保证共享变量的线程安全。
struts2的action是线程安全的,每次请求都会new 一个action
springmvc的Controller非线程安全,不能保证共享变量的线程安全。
影响线程安全性能因素
- 线程上下文切换
- 阻塞。阻塞会导致线程状态的切换,这也会产生额外的开销
性能优化
- 缩小锁的范围。 将一些与锁无关的逻辑代码移出锁范围
- 减少锁的竞争。 设置合理的线程数量,避免频繁上下文切换导致额外的开销
- 减少锁的粒度。 若锁包含多个相互独立的对象,那么可以试着建立多个锁,分别负责相应的对象。
- 锁分段。例如concurrentHashMap实现原理
- 替代独占锁。例如用CAS、读写锁等。