单例模式中关于线程同步问题,先谢了
java ee中,有一dao调数据库,该dao实现单例模式,即有
public class PersonDAO{
private static PersonDAO personDAO = new PersonDAO();
private PersonDAO(){}
public static PersonDAO getInstance(){
return personDAO;
}
}
这样可实现一个单例,但是有一个疑问:
1.当两个浏览器(也就是两个线程)同时调用PersonDAO时,这两个线程是不是同步的?
(也就是说a线程获得personDAO对象时,b线程只能等待a线程调用结束?)
2.别人说两个线程可以并发调用PersonDAO,我感觉很奇怪,personDAO是static的,也就是说在内存中只有一份,怎么可以同时被两个线程获取呢?
------解决方案-------------------- public class PersonDAO
的单例模式和并发没有任何关联!
单例模式,在jvm中只有一个对象!多个线程调用这个对象的方法,没有任何问题的,
不过非常重要的原则就是:不要再DAO中写成员变量,
如
public class PersonDAO
private String id;
private String name;
private String user;
上面的成员数据都存在一个对象中,会使数据大乱!
你的数据,VO(value object)都通过方法参数传递!
如:
public class PersonDAO
public void save(User user){代码}
public void update(User user){}
这样每个线程调用就不会有问题了!
这些概念也容易混淆,spring中的IoC的bean注入,都是单子模式,没有问题的!
------解决方案-------------------- 引用楼主 walkiing 的帖子: 这样可实现一个单例,但是有一个疑问: 1.当两个浏览器(也就是两个线程)同时调用PersonDAO时,这两个线程是不是同步的? (也就是说a线程获得personDAO对象时,b线程只能等待a线程调用结束?) 2.别人说两个线程可以并发调用PersonDAO,我感觉很奇怪,personDAO是static的,也就是说在内存中只有一份,怎么可以同时被两个线程获取呢?
------解决方案-------------------- 同一个对象怎么不能被多个线程调用呢,没有问题的,只是不是同步的,也就是说你的这个对象不是线程安全的,方法可以被多个线程同时使用,这也就是1楼兄弟所说的你要是在该对象里有成员变量,那这些值就得不到保证了,因为你是单例,通过具体的方法参数来用本地变量就OK了
------解决方案-------------------- 一个对象(数据)被多个线程访问,有两种方式:
1.非写操作, 即各个线程只是读其中的数据,这时不需要同步,因为线程之间读到的数据是相互之间没有影响的,这时减弱为互斥(即一个时间内只能有一个线程对其进行读)
2.写操作 这涉及到数据的统一性,因此也要互斥,但是如果a线程的处理结果要为b线程所用,那么加强为a,b线程同步
------解决方案-------------------- 探讨 Landor2004 说得有点意思了 其实我就是想知道 既然是同一个对象(static的嘛),怎么能同时(也就是并发)被两个线程调用呢? 我觉得是不是分身术.. :)
------解决方案-------------------- 探讨 这个是叫什么饿汉式单例,不需要线程同步 另外一种懒汉式的,就是调用方法时才生成对象这种才需要同步
------解决方案-------------------- 探讨 引用: public class PersonDAO 的单例模式和并发没有任何关联! 单例模式,在jvm中只有一个对象!多个线程调用这个对象的方法,没有任何问题的, 不过非常重要的原则就是:不要再DAO中写成员变量, 如 public class PersonDAO private String id; private String name; private String user; 上面的成员数据都存在一个对象中,会使数据大乱! 你的数据,VO(value object)都通过方法参数传递! …
------解决方案-------------------- 首先,建议楼主先抛开高层的概念,了解一下最基本的东西。
类是什么?类就是一堆抽象的代码,我们人类的概念,计算机不管;
对象是什么?对象就是一块内存,计算机仅仅认为它是一块内存;
单例是什么?单例就是仅仅有一块这样的内存,别的地方没有同样的;
线程是什么?线程就是一个过程,拥有一个跑起来的环境(堆栈....);
并发是什么?并发就是多个过程(线程)进展的逻辑时间没有关系(姑且先不管与并行的区别);
同步是什么?同步就是多个过程进展的逻辑时间的严格顺序性。
明白了以上的概念以后,我们来看看你的问题:
1.两个线程是否同步呢?实际上两个线程在没有显式同步的情况下就是不同步的,那么是否会引起并发问题呢?答案是如果你的单例里面没有成员变量就不会有问题,因为那个单例没有成员变量就剩下了一堆方法,而方法是在代码段里面的,进一步,线程拥有自己的堆栈,所有方法调用都在自己堆栈上进行,数据都是自己通过参数提供的,肯定在自己的存储空间(局部变量在堆栈,全局变量共享,靠线程安全解决),操作自己的堆栈别人管的着吗?但是,如果你的单例有成员变量,那么,操作成员变量就不是在自己的堆栈了,而是在单例的存储区,因此会有多个线程同时操作,从而引起问题。
2.为何两个线程都可以得到单例的对象呢?实际上,看了上面的分析以后,单例只不过是一块内存而已,底层的操作全是指针操作(java里没指针,但jvm还是c实现的,根本操作还是指针),不同的线程获得同一个指针难道有何问题吗?
希望对lz有帮助