线程

69 阅读5分钟
  • 线程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去启动线程的
  • 死锁的产生条件?如何避免死锁?

    • 死锁产生条件

      • 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进行修改,因为其他线程拿不到锁。
    • 有序性。要讲有序性要先理解指令重排序的概念,我们处理器为了提高运行效率,可能会对代码的执行顺序进行优化,但它不会影响代码的最终执行效果,因为指令重排序会考虑到指令之间的数据依赖性,但是当多线程进行操作的时候,指令重排序就可以会引发逻辑性问题。而有序性就是避免了指令重排序