-
线程start方法是否可以立马执行线程?
- 不能。线程start方法是线程就绪状态,并不意味着线程可以马上执行,具体执行时机取决于cpu调度
-
java设置线程优先级靠谱吗?
- 不靠谱。java可以设置线程的优先级,但这样设置有风险,并不可靠,因为高优先级线程只是得到cpu执行的概率比较大而已,并不一定比低优先级的线程优先执行
-
线程sleep跟wait的区别?
- sleep结束之后,线程会恢复到就绪状态等待cpu执行,wait则需要notify唤醒
- wait会释放锁,sleep不会
-
可以使用stop中断线程吗?
- 最好不要使用stop中断线程,因为这样做很暴力,危险,可以使用interrupt标记协作的方式停止,不过如果线程调用了sleep会收到一个*java.lang.InterruptedException异常,将会清除interrupt标记,可以在捕获异常里面再次调用interrupt()进行标记
-
yield方法的作用?
- 让出执行权力
-
join的作用?
- 可以让线程按顺序执行,比如在main线程调用了子线程A.join,会让main线程进入等待状态,等到A线程执行完毕才会继续往下执行
-
类锁跟对象锁的区别?
- 作用在静态方法上的锁称之为类锁,还可以通过synchronized(类.class)方式
- 作用在非静态方法上的锁称之为对象锁,还可以通过synchronized(类.this)方式
-
启动的线程的方式有几种?
- Thread源码注释明确了开启线程方式只有两种
- 1.继承Thread
- 2.实现Runnable接口
- ps:实现callbale接口本质还是实现了Runnable接口然后交给Thread去启动线程的
- Thread源码注释明确了开启线程方式只有两种
-
死锁的产生条件?如何避免死锁?
-
死锁产生条件
- n个操作者抢夺m个资源,切n,m>=2,n<=m
- 抢夺资源顺序不对(互斥)
- 拿到资源不放手
-
避免死锁的发生
- 修改争夺资源的顺序
- 使用手动锁ReentrantLock.tryLock
-
-
什么是活锁
- 多个线程进行ReentrantLock.tryLock,不停的获取锁释放锁
-
乐观锁和悲观锁
- 乐观锁CAS机制
- 悲观锁synchronized
- 乐观锁的性能一般是优于悲观锁的,因为synchornized会造成等待线程的上下文切换,每一次切换都是很耗时间的,乐观锁的原理是线程通过不停的循环,进行cpu cas判断值是否被修改,所以没有上下文切换,耗时更短
-
CAS存在的问题
-
ABA问题
- 线程2 将A改成C又改成了A,导致线程1进来的时候,拿到的是A,以为没有被改动过
-
开销问题
- 如果线程竞争非常激烈,导致线程一直在循环,会影响cpu性能
-
只能保证一个共享变量的原子操作
-
-
AQS与CLH队列锁
- AQS内部state专门用来保存当前的同步状态,如果要实现自己的同步工具类例如ReentrantLock,其实是利用AQS的模版方法设计模式,设计自己的同步工具类。
- AQS内部实际是一个CLH队列锁,队列+自旋,将需要拿锁的线程打包成一个node,里面有一个pred字段跟locked字段,pred字段指向前一个节点,locked字段标记是否需要拿锁,每一个node通过自旋判断前一个节点node是否为false释放了锁,如果释放了锁,就去拿锁。这也是一个公平锁,凡是想拿锁的线程,都要乖乖的插入到尾部队列去,非公平锁是指不乖乖排队,而是插队
-
线程的可见性,原子性,有序性,volatile
- 我们的变量比如int i,i其实是放在主内存中的,但是每个线程如果对i进行操作不会直接在主内存中进行操作,而是会将i复制到线程内部的工作内存中进行,当进行了i+1之后,再将值更新到主内存中,所以线程间是不知道其他线程对i进行了操作的,这就叫可见性。
- 原子性是指,一个或多个操作,在执行过程中不会被打断,要么全部执行,要么都不执行,接上个例子,如果使用了volatile可以保证可见性,但不能保证原子性,因为,volatile的原理是线程在工作线程中执行完毕,必须马上更新大主内存中,而当其他线程执行的时候必须重主内存中进行读取最新的值,但是在读取的时候,线程有可能会进行上下文切换,这时候别的线程如果对i又进行了修改,在切回原线程,就会出问题,所以volatile不能保证原子性,synchronized可以保证原子性跟可见性,因为就算进行了上下文切换,其他线程也不能对i进行修改,因为其他线程拿不到锁。
- 有序性。要讲有序性要先理解指令重排序的概念,我们处理器为了提高运行效率,可能会对代码的执行顺序进行优化,但它不会影响代码的最终执行效果,因为指令重排序会考虑到指令之间的数据依赖性,但是当多线程进行操作的时候,指令重排序就可以会引发逻辑性问题。而有序性就是避免了指令重排序