Java内存模型

[高并发Java 三] Java内存模型和线程安全

不想你离开。 提交于 2020-02-29 06:33:01
网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存。数据在主存中会有一份,在工作内存中也有一份。工作内存和主存之间会有各种原子操作去进行同步。 下图来源于 这篇Blog 但是由于Java版本的不断演变,内存模型也进行了改变。本文只讲述Java内存模型的一些特性,无论是新的内存模型还是旧的内存模型,在明白了这些特性以后,看起来也会更加清晰。 1. 原子性 原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。 一般认为cpu的指令都是原子操作,但是我们写的代码就不一定是原子操作了。 比如说i++。这个操作不是原子操作,基本分为3个操作,读取i,进行+1,赋值给i。 假设有两个线程,当第一个线程读取i=1时,还没进行+1操作,切换到第二个线程,此时第二个线程也读取的是i=1。随后两个线程进行后续+1操作,再赋值回去以后,i不是3,而是2。显然数据出现了不一致性。 再比如在32位的JVM上面去读取64位的long型数值,也不是一个原子操作。当然32位JVM读取32位整数是一个原子操作。 2. 有序性 在并发时,程序的执行可能就会出现乱序。 计算机在执行代码时,不一定会按照程序的顺序来执行。 class OrderExample { int a = 0; boolean flag = false;

深入研究Servlet线程安全性问题

旧时模样 提交于 2019-12-05 04:14:06
Servlet/JSP技术和ASP、 PHP 等相比,由于其多线程运行而具有很高的执行效率。由于Servlet/JSP默认是以多线程模式执行的,所以,在编写代码时需要非常细致地考虑多线程的安全性问题。然而,很多人编写Servlet/JSP程序时并没有注意到多线程安全性的问题,这往往造成编写的程序在少量用户访问时没有任何问题,而在并发用户上升到一定值时,就会经常出现一些莫明其妙的问题。 Servlet的多线程机制 Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。Servlet容器会自动使用线程池等技术来支持系统的运行. 这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web 应用 时如果不注意线程安全的问题,会使所写的Servlet程序有难以发现的错误。 Servlet的线程安全问题 Servlet的线程安全问题主要是由于实例变量使用不当而引起的,这里以一个现实的例子来说明。 Import javax.servlet. *;