不保证原子性:线程1从主内存中拿了一个值为1的数据到自己的工作空间里面进行加1的操作,值变为2,写回主内存,然后还没有来得及通知其他线程,线程1就被线程2抢占了,CPU分配,线程1被挂起,线程2还是拿着原来主内存中的数据值为1进行加1,值变成2,写回主内存,将主内存值为2的替换成2,这时线程1的通知到了,线程2重新去主内存拿值为2的数据。
禁止指令重排:首先指令重排是程序执行的时候不总是从上往下执行的,就像高考答题,可以先做容易的题目再做难的,这时做题的顺序就不是从上往下了。禁止指令重排就杜绝了这种情况。
(一般面试官开始问你会从java基础问起,一问大多数会问到集合这一块,而集合问的较多的是HashMap,这个时候你就可以往这些方向带着面试官问你,而且扩展的深度也够,所以上面的干货够你说个十来分钟吧,第一个问题拿下后,面试官心里至少简单你的基础够扎实,第一印象分就留下了)
Spring的AOP和IOC是什么?使用场景有哪些?Spring事务与数据库事务,传播行为,数据库隔离级别AOP:面向切面编程。
即在一个功能模块中新增其他功能,比方说你要下楼取个快递,你同事对你说帮我也取一下呗,你就顺道取了。在工作中如果系统中有些包和类中没有使用AOP,例如日志,事务和异常处理,那么就必须在每个类和方法中去实现它们。 代码纠缠每个类和方法中都包含日志,事务以及异常处理甚至是业务逻辑。在一个这样的方法中,很难分清代码中实际做的是什么处理。AOP 所做的就是将所有散落各处的事务代码集中到一个事务切面中。
场景
比方说我现在要弄一个日志,记录某些个接口调用的方法时间。使用Aop我可以在这个接口前插入一段代码去记录开始时间,在这个接口后面去插入一段代码记录结束时间。
又或者你去访问数据库,而你不想管事务(太烦),所以,Spring在你访问数据库之前,自动帮你开启事务,当你访问数据库结束之后,自动帮你提交/回滚事务!
异常处理你可以开启环绕通知,一旦运行接口报错,环绕通知捕获异常跳转异常处理页面。
动态代理
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。它的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
IOC:依赖注入或者叫做控制反转。
正常情况下我们使用一个对象时都是需要new Object()的。而ioc是把需要使用的对象提前创建好,放到spring的容器里面。
所有需要使用的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。DI(依赖注入)其实就是IOC的另外一种说法,其实它们是同一个概念的不同角度描述。
场景:
正常情况下我们使用一个对象时都是需要new Object() 的。而ioc是把需要使用的对象提前创建好,放到spring的容器里面。需要使用的时候直接使用就行,而且可以设置单例或多例,非常灵活。
我们在service层想调用另外一个service的方法,不需要去new了,直接把它交给spring管理,然后用注解的方式引入就能使用。
IOC三种注入方式
(1)XML:Bean实现类来自第三方类库,例如DataSource等。需要命名空间等配置,例如:context,aop,mvc。
(2)注解:在开发的类使用@Controller,@Service等注解
(3)Java配置类:通过代码控制对象创建逻辑的场景。例如:自定义修改依赖类库。
什么是事务?
事务是访问并可能更新数据库中各种数据项的一个程序执行单元。
Spring事务与数据库事务关系?