网站开发技术和工具,wordpress 上帝模式,营销型设计网站,简述网站的设计流程转载自 java面试线程必备知识点#xff0c;怼死面试官#xff0c;从我做起
|--多线程一定好么#xff1f;
cpu密集不好 io密集好
|--如何减少上下文切换#xff1a;
无锁并发#xff08;数据id根据Hash分段#xff09;、CAS、最少线程
|--java线程避免死锁#xff…转载自 java面试线程必备知识点怼死面试官从我做起
|--多线程一定好么
cpu密集不好 io密集好
|--如何减少上下文切换
无锁并发数据id根据Hash分段、CAS、最少线程
|--java线程避免死锁
避免一个线程同时有多个锁
避免一个锁占用多个资源
lock.tryLock代替内部锁
内存屏障限制命令操作顺序有LoadLoad、LoadStore、LoadStore、StroreStreo四种屏障
缓冲行cpu缓存最小储存单位
写命中缓存有直接写入缓存
缓存一致性主存改变其他缓存改变(read、load、use绑定)
顺序一致性单个线程内执行结果一定是不变的但依然有指令重排只是结果不受影响的重排
|--八个CPU原子命令
lock、unlock、read、load、use、assign、store、write
|--volatile做的事
1.lock前缀指令使缓存行立即写入内存assign、store、write绑定
2.其他cpu缓存无效
3.加入内存屏障
使用前景不依赖于上次数据
使用案例itmp i;tmptmp1;i tmp;
64位机器跑32位jvmlong和double2段分2次计算不加volatile会导致结果前32位是一个线程结果后32位一个线程结果
|--synchronized
对象加锁Monitor对象monitorenter和monitorexit命令实现
锁升级
|--ReentrantLock 可重入锁
通过CVS等实现比synchronized效率略高有公平锁非公平锁
锁可多次进入并把拥有数
lock(), 如果获取了锁立即返回如果别的线程持有锁当前线程则一直处于休眠状态直到获取锁
tryLock(), 如果获取了锁立即返回true如果别的线程正持有锁立即返回false
|--ReentrantReadWriteLock
read/write两把锁
写锁与ReetrantLock类似只有写锁读锁都没被占用才获得锁
读锁拥有数是多个线程的每个线程拥有数只能自己通过ThreadLocal记录
写锁结束降级读锁避免可见性问题
|--Lock和synchronized区别
Lock是通过代码级实现cvs
synchronized是通过jvm的monitor实现的
还多了 锁投票定时锁等候和中断锁等候等特性
使用ReentrantLock如果A不释放可以使B在等待了足够长的时间以后中断等待而干别的事情
|--AQSAbstractQueuedSynchronized
有队列有state、进入会先自旋再阻塞默认非公平队列唤醒了调用tryAcquire不一定能获取锁
|--java对象头
MarkWord 长度32/64存储hashCode或者锁信息
|--CAS unsafe.compareAndSwap(对象地址原来值要修改值)
unsafe是通过操作系统实现CMPXCHG指令如果失败返回false
|--CAS使用自旋锁、自适应自旋锁
|--锁的升级
偏向锁(markword指向所在线程代价低两个线程则停安全点撤销)-轻量级线程markword置换到拥有者线程线程对象互指。两个线程则b线程自旋等待-重量级锁syn、reeentrantLock
比较
偏向锁 加锁解锁消耗极少锁竞争的安全点带来消耗。 适用于一个线程
轻量级锁响应快自旋消耗cpu 追求响应时间同步块非常快
重量级 追求吞吐量同步块执行时间长
|--处理器实现原子性策略
LOCK#信号是一个线程独占共享内存(通过锁住主内存总线之后优化成缓存锁)
缓存锁保证原子性
|--java原子实现
锁和CAS
CAS局限性ABA问题过程无感知、循环时间开销大、一次保证一个变量
|--内存模型对底层抽象
线程通信方式:
内存模型共享内存
消息传递A复制到主内存再从主内存写到B
管道输入流输出流PipedReader,PipedWriter,PipedInputstream,PipedOutputStream
内存模型本地内存共享变量副本、局部变量、主内存共享变量
指令重排序编译优化重排、并行重排、内存重排
|--final域重写规则
构造函数内final写入与被构造的对象引用赋值不能重排序objthis会引发逃逸例如此时别的线程调用obj.ifinal的i变量还没初始化
初次读含final域对象与随后读final区域不能重排
|--单例模式问题
实例化分为1.开辟空间memory 2.初始化对象 3.设置instance指向memory。
指令重排可能是1-3-2 , 若2还未执行B线程认为instance非空直接调用instance导致错误
解决方案1.volatile禁止重排序 2.匿名内部类连自己加锁都不用类自带实例化锁
|--为什么使用多线程
1.多处理器发挥功效
2.更快相应一个下订单带来一系列操作如何快速成功线程派发分任务执行
|--java优先级
不一定有用主要是靠操作系统底层实现
|--interrupt
interrupt不会真的终止只是一种协作机制
interrupt()将会设置该线程的中断状态位即设置为true
使用Thread.currentThread().isInterrupted()方法因为它将线程中断标示位设置为true后不会立刻清除中断标示位即不会将中断标设置为false
thread.interrupted()该方法调用后会将中断标示位清除即重新设置为false
一个线程处于了等待状态thread.sleep、thread.join、thread.wait则在线程在检查中断标示时如果发现中断标示为true则会在这些阻塞方法调用处抛出InterruptedException异常并且在抛出异常后立即将线程的中断标示位清除即重新设置为false。抛出异常是为了线程从阻塞状态醒过来并在结束线程前让程序员有足够的时间来处理中断请求。
锁的情况下不会被中断影响
|--阻塞状态与等待区别
阻塞是进锁里等待是wait、sleep。sleep设置时间状态叫做超时等待状态
|--线程的应用
1.等待之后超时
while(结果未返回 时间未到)
wait();
2.线程池
要有队列状态
Worker实现Runnable接口循环从jobs队列取任务执行获取不到就wait();
execute(Job job)时唤醒jobs
3.基于线程池Web服务器
思路开一个Socket服务每次accept后把这个一对一服务放封装成job类放到jobs队列里
|--LockSupport
工具类有park、unpark阻塞唤醒线程
|--Condition
相当于Lock中的wait和notify,区别是wait等待队列只能有一个Condition可以有多个
Condition队列类似于AQS队列
每个Condition下面有一个等待await的等待队列
Lock.newCondition()获取condition
Lock.await(); wait
Lock.singal();notify
|--ConcurrentHashMap
问题HashMap线程不安全导致Entry链表编程环引发死循环。
HashTable效率低
解决Segment包含HashEntry数组
Segment是一种可重入锁ReentrantLock
实现segment数量是2的n次方默认16
每一个segment的容量每个segment里HashEntry*负载因子
如何放入数据再散列确保数据分散后放入segment
get方法不加锁而是用volatile
1.8更新没有了segment横向用Node链表替代Node被调用取时就synchronize加锁。当没Node底下链表超过8个将加锁
|--ConcurrentLinkedQueue
非阻塞
入队定位尾节点不成功cvs重试为了减少CVS控制尾节点更新频率
出队