首页 文章 精选 留言 我的

精选列表

搜索[Java],共10000篇文章
优秀的个人博客,低调大师

Java内存模型-volatile内存语义

章节目录 1.volatile 的特性 为什么volatile修饰变量的写操作不是原子性的? 2.volatile 写-读建立的 happens-before 关系 3.volatile 写-读的内存语义 1.volatile 的特性 首先应该明确的一点是:当声明共享变量为volatile后,对这个变量的读/写(分为单元素读写,与复合写操作)。不同的读写模式下,volatile变量对写操作的原子性体现是不一样的。 理解volatile特性的一个好办法是把对volatile变量的单个读/写,看成是同一个锁对这些单个读/写操作做了同步,示例代码如下所示: class VolatileFeaturesExample { volatile long vl = 0L; public void set(long l){ vl = l; } public void getAndIncrement() { vl++; } public long get(){ return vl; } } 假设有多个线程调用上述程序中的3个方法,这个程序语义和下面的程序语义等价 class VolatileFeaturesExample { long vl = 0L; public synchronized void set(long l){ vl = l; } public void getAndIncrement() { long temp = get(); temp +=1L; set(temp); } public syntronized long get(){ return vl; } } 解释 如这两个程序所示,一个volatile 变量的单个读/写操作,与一个普通变量的读/写操作都是使用同一个锁来同步,他们之间的执行效果相同。 锁的happens-before规则(保证前一个操作结果对后一个操作立即可见)保证释放锁和获取锁的两个线程之间的内存可见性。这很好的解释了对于一个volatile变量的读,总能看到任意线程对这个volatile变量最后的写入。 锁的语义决定了临界代码区的执行具有原子性。这意味着,即使是64位的long型和double型变量,只要它是volatile变量,对该变量的单个读/写就具有原子性,如果是多个volatile操作,或这是volatile++这种复合操作,这些操作在整体上是不具有原子性的。 volatile 自身特性: 1.内存可见性:对一个volatile变量的读,总能看到任意线程对这个volatile变量 最后的写入(内存可见性保证) 2.原子性:对任意单个volatile变量的单独的读写操作,都具有原子性。但对于 volatile++这种复合操作不具有原子性。 2.volatile 写-读建立的 happens-before 关系 JMM基于共享内存模型实现线程之间的通信 从jdk1.5 开始 volatile 变量的写-读可以实现线程之间的通信。 volatile & synchronized内存语义 从内存语义来说,volatile的写-读与锁的释放-获取有相同的内存效果:volatile 写和锁释放有相同的内存语义;volatile读与锁的获取有相同的内存语义。 下面为volatile变量示例代码: class VolatileExample { int a = 0;//其实是线程共享变量 volatile boolean flag = false; public void writer(){ a = 1; //1 flag = true; //2 } public void reader(){ if(flage){ //3 int i = a; //4 ...... } } } 假设线程A 执行 writer() 方法之后,线程B 执行reader() 方法。根据happens-before 规则,这个过程建立的happens-before规则可以分为三类: 1.根据程序次序规则,1 happens before 2;3 happens before 4. 2.根据volatile规则,2 happens-before 3 3.根据happens-before c传递性规则 1 happens-before 4 图形化形势如下图所示: volatile-写-读 happens-before 关系 A线程在写一个volatile变量后,B线程读同一个volatile变量。A线程在写volatile之前所有的可见共享变量,在B线程读到同一个volatile变量之后,将立即变得对B线程可见。 4. volatile 写-读的内存语义 ** volatile 写内存语义 ** 当写一个volatile变量时,JMM会把该线程对应的本地内存的变量中的变量值强制刷新到主内存。 volatile 读的内存语义 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。 volatile内存语义 总结 线程A 写一个volatile 变量,实质上是线程A 向接下来读取这个volatile变量的某个线程发出了(其对共享变量所做修改的)消息。 线程B 读一个volatile 变量,实质上是线程B 接收了之前某个线程发出的(在写这个volatile变量之前对共享变量所做修改)消息。 线程A 写一个volatile 变量,随后线程B读这个volatile变量。这个过程实质上是线程A通过主内存向线程B发送消息。

优秀的个人博客,低调大师

Java AOP(面向切面编程)实现

动态代理 AOP概念解释 AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。 AOP中的概念 Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象。joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在Spring中,这些点指的是方法,因为Spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器。Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即joinpoint的集合。Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知。通知分为前置通知、后置通知、异常通知、最终通知、环绕通知。我们就以CGlibProxyFactory类的代码为例进行说明: public class CGlibProxyFactory implements MethodInterceptor { private Object targetObject; // 代理的目标对象 public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass()); // 设置目标类为代理对象的父类 enhancer.setCallback(this); return enhancer.create(); } // 从另一种角度看: 整个方法可看作环绕通知 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { PersonServiceBean bean = (PersonServiceBean)this.targetObject; Object result = null; if (bean.getUser() != null) { // 有权限 // ...... advice() ----> 前置通知(所谓通知,就是我们拦截到业务方法之后所要干的事情) try { result = methodProxy.invoke(targetObject, args); // 把方法调用委派给目标对象 // ...... afteradvice() ----> 后置通知 } catch (RuntimeException e) { // ...... exceptionadvice() ----> 异常通知 } finally { // ...... finallyadvice() ----> 最终通知 } } return result; } } Target(目标对象):代理的目标对象。Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入。Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类(代理类)动态地添加一些方法或Field。 AOP带来的好处:降低模块的耦合度;使系统容易扩展;更好的代码复用性。 2. JDK实现 1). 创建Person接口 public interface PersonService { /** * 保存 * @param name 名称 */ public void save(String name); /** * 根据ID更新名称 * @param name 姓名 * @param personId 人员ID */ public void update(String name, Integer personId); /** * 根据ID获取名称 * @param personId 人员ID * @return 名称 */ public String getPersonName(Integer personId); } 2). 创建实现Person接口的实现类PersonImpl public class PersonServiceImpl implements PersonService{ private String user = null; public void setUser(String user) { this.user = user; } public String getUser() { return user; } public PersonServiceImpl() { } public PersonServiceImpl(String user){ this.user = user; } @Override public void save(String name) { System.out.println("我是save方法"); } @Override public void update(String name, Integer personId) { System.out.println("我是update方法"); } @Override public String getPersonName(Integer personId) { System.out.println("我是getPersonName方法"); return "xxx"; } } 3). 创建代理类PersonServiceImplProxy public class PersonServiceImplProxy implements InvocationHandler { private PersonService personService; public PersonService createProxy(PersonService personService) { return (PersonService) Proxy.newProxyInstance(PersonServiceImplProxy.class.getClassLoader(), personService.getClass().getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { PersonServiceImpl pImpl = (PersonServiceImpl) this.personService; Object result = null; // 如果不等于null则表示有权限 if (null != pImpl.getUser()) { // 执行方法 result = method.invoke(personService, args); } return result; } } 4). 创建Demo类测试 public class Demo { public static void main(String[] args) { PersonServiceImplProxy proxy = new PersonServiceImplProxy(); PersonService service = proxy.createProxy(new PersonServiceImpl("mazaiting")); service.save("123"); } } 打印结果: 图1.png 5). 更改测试代码 public class Demo { public static void main(String[] args) { PersonServiceImplProxy proxy = new PersonServiceImplProxy(); PersonService service = proxy.createProxy(new PersonServiceImpl()); service.save("123"); } } 打印结果: 图2.png 3. CGlib实现AOP功能 动态代理技术只能是基于接口,那如果这个对象没有接口,就要使用CGlib这个工具包。 1). 创建PersonService类 public class PersonService { private String user = null; public void setUser(String user) { this.user = user; } public String getUser() { return user; } public PersonService() { } public PersonService(String user){ this.user = user; } public void save(String name) { System.out.println("我是save方法"); } public void update(String name, Integer personId) { System.out.println("我是update方法"); } public String getPersonName(Integer personId) { System.out.println("我是getPersonName方法"); return "xxx"; } } 2). 创建CGlibProxyFactory类 public class CGlibProxyFactory implements MethodInterceptor { // 代理的目标对象 private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; // 该类用于生成代理对象 Enhancer enhancer = new Enhancer(); // 设置目标类为代理对象的父类 enhancer.setSuperclass(this.targetObject.getClass()); // 设置回调用对象本身 enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { PersonService service = (PersonService) this.targetObject; Object result = null; // 有权限 if (null != service.getUser()) { // 把方法调用委派给目标对象 result = methodProxy.invoke(targetObject, args); } return result; } } 3). 创建Demo测试类 public class Demo { public static void main(String[] args) { CGlibProxyFactory factory = new CGlibProxyFactory(); PersonService service = (PersonService) factory.createProxyInstance(new PersonService("mazaiting")); service.save("999"); } } 4). 打印结果 图3.png

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册