单例模式与多线程之间的关系总结

  近日笔者被多线程与单例对象之间的关系产生了混淆。经过了一段时间的查阅,理清了二者之间的管理,现作笔记梳理。若有不足,欢迎指出:)前端

在我在考虑考虑他们的时候思考了如下几个问题:spring

一、咱们一般都将dao层(数据库链接层)设置成单例,这样的话若是每次处理数据库中的数据都须要同一个对象去处理的话,处理数据的性能彻底得不到保证。数据库

二、ssh中为何struts2中的action层必须建立多例?而ssm中springmvc的Controller层不须要建立多例?安全

三、一个单例模式建立的对象是能够同时被多个线程处理的,若是一个对象被多个线程同时处理的话,颇有可能出现线程同步问题(关于线程中的安全问题,对对象加锁请参考:http://lavasoft.blog.51cto.com/62575/99155/),若是两个线程同时访问一个函数的话,要不要加锁呢,加锁怎么加,不加又怎样?session

 

理解思路:多线程

  咱们知道一个对象是能够同时被多个线程进行调用的,一个单例对象每次都只能有一个线程进行调用的话,就不会出现线程中的安全问题了。只有一个当一个对象加锁后,才能作到每次只能有一个线程进行处理。mvc

  多个线程处理一个对象的过程是怎么样的呢?每次建立一个线程,jvm虚拟机就会在内存中给每一个线程分配独立的堆栈存储空间ssh

  

  单例模式建立的对象在内存中是如何加载的呢?全部的单例模式的对象都是经过静态方法获取的,也就是说,每一个单例模式的对象都是存储在静态共享区中!jvm

  一个普通对象在一个线程中是怎么加载的呢?函数

  在一个线程中,若是建立一个对象,会先在堆内存中开辟一个存储空间,该对象在建立的时候就会在栈内存中开辟空间,调用其构造方法、静态代码块等…当方法结束,会在栈内存中清除。一个线程在调用这个对象的方法的时候会在栈内存中建立一个空间存储对象方法。

  同理,对于在一个线程加载单例模式对象的时候,它会在静态共享区获取单例对象,而后在调用对象方法(非静态)的时候会在本身的栈内存开辟一个空间,因此每一个线程在调用同一个对象的方法的时候都会在它的栈内存中开辟一个独立的内存空间。这说明了多线程处理同一个对象的时候若是不涉及到对象的共有属性值,不会存在线程安全问题。

   如今对文章开头的内容进行一点解释:

一、咱们一般都将dao层(数据库链接层)设置成单例,这样的话若是每次处理数据库中的数据都须要同一个对象去处理的话,处理数据的性能彻底得不到保证。

  答:由于咱们每次处理数据库是使用session进行数据库的交互处理,而session是由SessionFactory建立的,SessionFactory将建立出的session放入session链接池中,链接池中的session均为不一样的对象。咱们指的建立单例对象在这里指的是SessionFactory。

二、ssh中为何struts2中的action层必须建立多例?而ssm中springmvc的Controller层不须要建立多例?

  答:struts2中由于将前端获取的值所有都存储在对象属性中,因此确定须要设置为多例,springMVC中,前端获取的值直接进入方法中,因此设置为单例模式不会存在线程安全问题。

三、一个单例模式建立的对象是能够同时被多个线程处理的,若是一个对象被多个线程同时处理的话,颇有可能出现线程同步问题(关于线程中的安全问题,对对象加锁请参考:http://lavasoft.blog.51cto.com/62575/99155/),若是两个线程同时访问一个函数的话,要不要加锁呢,加锁怎么加,不加又怎样?

   答:一个单例模式的方法能够同时被多个线程处理,多个线程若是不是同时处理一个对象的共有属性,则不会出现线程问题,即便是方法中的属性若是两个线程同时访问同一个方法的时候,若是这个方法中没有共有的属性,则不须要加锁,反之则须要加锁。

相关文章
相关标签/搜索