java基础知识扫盲

1、string为什么不可继承?

答:因为string是用final修饰的不可变类,不可以被继承;

       为什么要用final修饰?

答:安全,设计者将string设为共享的,子类不可以修改,因此设置为final;

       效率,共享的效率更高;

2、怎样减少线程的上下文切换?

答:减少并发线程数,尽量使用无锁编程,CAS算法

       什么是CAS算法?

答:compare and swap意思是先比较旧的预期值和原来内存中存储的值相等,再更改为目标值,是一种乐观锁,适用于读多写少的情况,效率较高,只有极少的情况会发生冲突

       CAS会有ABA问题应怎么解决?

答:ABA问题是指旧的预期值被更改为和原来内存中存储的值相等,已经发生过一次更改,这种情况可以通过版本号(AtomicStampedReference)、时间戳来解决,比较最初获取的版本号和更改前获取的版本号是否一致,一致则更改,更改后都将版本号+1

3、说下valitile关键字的作用?

答:可见性:当多个线程共同访问同一变量,当其中一个线程修改了该变量,其他线程都能立刻看到修改的值

       有序性:防止指令重排序,程序执行顺序按当前代码顺序执行

       注:指令重排序不会影响单个线程的执行,但会影响多个线程并发执行的结果

       https://www.cnblogs.com/dolphin0520/p/3920373.html

内存屏障会提供3个功能:

  1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

  2)它会强制将对缓存的修改操作立即写入主存;

  3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

      volatile可以保证原子性吗?

答:不是,两个线程同时从内存中读取变量的值i=10到自己的工作内存,线程a和线程b同时做自增操作+1,写入工作内存,再写入内存,两个线程分别自增一次,但内存中的结果只增加1,因此volatile不保证原子性

4、描述下java内存模型

答:Java内存模型规定所有的变量都是存在主存当中,每个线程都有自己的工作内存。线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作。并且每个线程不能访问其他线程的工作内存。

5、描述下happens-before原则(先行发生原则)

答:Java内存模型具备一些先天的“有序性”

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
  • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

猜你喜欢

转载自www.cnblogs.com/tilamisu007/p/9554027.html