我的理解:
成员变量是保存在堆中,所有线程都能访问;局部变量是保存在每条线程的各自的栈中,互不影响。
单例模式下成员变量会有线程安全问题,因为每条线程都可能会访问到该成员变量;多例模式下则不会有这问题,不会有这问题的原因是 栈中的对象分别指向堆中属于自己的成员变量。
我的理解是否有问题?或者有什么补充的。
谢谢!
因为spring是默认是单例模式,而单例模式有三种常用的实现形式都是静态化实例对象。既然静态化了,那么就属于静态区,被多线程共享(每个线程在虚拟机栈里都有自己的栈空间),所以线程不安全。但是如果自己new一个对象是属于线程内部的局部变量,存在new他的那个线程的一个栈帧里,就是线程安全的。所以总结起来就是,这两种的对象存在不一样的地方,共享范围也不一样,所以有的线程安全,有的不安全,就会出现你说的那种情况,望采纳,谢谢
线程安全的原因在于并发操作同一个对象无法保证操作的原子性、事务性和一致性。
“多例模式下则不会有这问题,不会有这问题的原因是 栈中的对象分别指向堆中属于自己的成员变量。”
我不知道你说的多例模式是什么模式,也许你想表达的是多个对象实例的情况,这种情况一样可能有线程安全的问题,体现在多个实例访问类的静态成员,多个线程访问同一个实例。
虽然变量是在堆栈上定义的,但是指向的对象还是在堆上的,因此通过某些方式它们还是会被别的线程访问到。比如说借助参数、全局变量、装入了arraylist等。
不管单例还是多例,只要多个线程能够**访问并改变****同一个对象实例**,都可以说成在线程安全。
读了几遍你写的,还是读出了毛病。。。
其实可以这么理解的,单例是多个线程访问 1个资源,肯定有线程安全问题,
多例虽然有多个对象(比如说有2个吧),但是访问的线程如果有10个,其中5个访问资源1,这就相当于5个线程访问同一个资源,也就是转化成上面
单例线程不安全的原因,所以单例还是多例只要是多线程都不安全,
你说错的原因是,虽然局部变量是保存在各自的栈中,但是多例中的每个例,都是全局变量,保存在堆中,,差点把我绕进去
使用单例模式简单来说生成对象时属性都一样,即你new一百次,通过方法得到的结果都一样(比如获取静态资源文件,工具类等). 所以就没必要生成多个对象浪费服务器内存,他和静态类又不同,因为单例本质也是对象系统,长期不使用,也会给cg清除.但是静态类不同,静态类的成员变量和有静态方法会在程序的整个生命周期存在,比如在服务器内在中加载后服务器不关,就会一直存在,同理的有servlet的ServletContext对象和jsp的application对象
才疏学浅 你可以参考一下这个http://www.mamicode.com/info-detail-1728587.html
线程安全问题是多线程访问共享数据才会存在的,这包括两种情况,一是多线程访问单例的成员变量,二是多线程访问静态变量(数据库这里这就不算了)
线程内部不会产生安全问题,从java内存模型来看,一个线程对于对象的操作流程应该是,访问主存中的对象并复制到工作内存当中,在工作内存中对副本做相应操作,操作完成后再写入主存,线程见会产生线程安全问题,正是因为一个线程在操作工作内存中的副本时,在写入主存之前,其他线程是不可见的,所以会产生问题,而线程内部,无论哪个方法怎么执行,对副本都是可见的,你说的两种情况其实也是不存在的,情况1,如果你在一个线程中,一个方法执行到一半,去执行另一个方法,代码怎么写?肯定是在第一个方法中调用第二个方法,那么第二个方法执行完,第一个方法的后半部分肯定要接着第二个的逻辑写,还接着第一个方法的前一半写,那就是代码写错了,情况2相同
楼主理解没问题,但既然是单例,为什么还要改变成员变量呢?
楼上的大佬们其实都说的很对,但是过于学术化不利于新人理解。
其实可以想简单点,java的对象就是一个独立的个体,比如说一个人,这一个人去做多件事当然是资源共享的,比如一张嘴不可能同时说次话。
多例与单例比只是多了几个人(对象),但是这其中任何一个人也不可能同时说两次话,也就是说同时有两个线程持有一个对象就是不安全的,
所谓的多例只是生产人(对象)的模式不同而且,与线程安全无关。
只是单例必然发生线程安全问题,才会常常与单例一起讨论。
个人理解,仅参考。
真的把我绕晕了,给你解决一下这个问题。
下面只针对**引用类型**来说一下多线程的安全问题,不包括基本类型:
总之,判断一个对象是否存在线程安全问题,就是看这个对象的全局变量是不是可以同时被多个线程访问修改。如果一个类没有全局变量,只有一大堆的方法和不能修改的常量,那你来多少线程访问都没事(这其实就是工具类)。
至于题主说的单例和多例,不能从类的角度分析线程是否安全,是要归到“对象”这个层面上进行分析。