线程的同步之Synchronized在单例模式中的应用
来源:互联网 发布:黄蜂数据 编辑:程序博客网 时间:2024/06/05 05:12
在单例模式中有一种懒汉式的单例,就是类初始化的时候不创建对象。等第一次获取的时候再创建对象。这种单例在单线程下是没有问题的获取的也都是同一个对象。但是如果放入多线程中就会获取多个不同对象问题。
1、首先来看一个懒汉式的单例模式:
//懒汉式的单例类
class
MyJvm{
private
static
MyJvm instance =
null
;
private
MyJvm(){}
public
static
MyJvm getInstance(){
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
}
测试类:
public
static
void
main(String[] args) {
MyJvm jvm1 = MyJvm.getInstance();
MyJvm jvm2 = MyJvm.getInstance();
System.out.println(jvm1);
System.out.println(jvm2);
}
测试结果:单线程的情况下,懒汉式的结果是没问题的。
com.fz.Thread.syn.MyJvm@18f1d7e
com.fz.Thread.syn.MyJvm@18f1d7e
2、现在加入多线程访问的情况
编写一个多线程的类:
//多线程类
class
MyJvmThread
extends
Thread{
@Override
public
void
run() {
System.out.println(Thread.currentThread().getName()+
"-->创建:"
+MyJvm.getInstance());
}
}
然后再使用多线程测试:
public
static
void
main(String[] args) {
MyJvmThread thread1 =
new
MyJvmThread();
MyJvmThread thread2 =
new
MyJvmThread();
thread1.start();
thread2.start();
}
测试结果如下:多线程情况下就出现了问题,可以获取多个不同的对象
Thread-0-->创建:com.fz.Thread.syn.MyJvm@785d65
Thread-1-->创建:com.fz.Thread.syn.MyJvm@3bc257
3、给单例加锁:直接加在方法上
修改MyJvm这个单例类:直接在方法上加锁(效率低)
//懒汉式的单例类
class
MyJvm{
private
static
MyJvm instance =
null
;
private
MyJvm(){}
public
static
synchronized
MyJvm getInstance(){
//这里在方法上直接加上synchronized
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
}
使用多线程的main方法测试:结果是正确的
Thread-1-->创建:com.fz.Thread.syn.MyJvm@2c1e6b
Thread-0-->创建:com.fz.Thread.syn.MyJvm@2c1e6b
虽然以上结果是正确的,但是存在效率问题。每个获取getInstance()方法的对象都需要锁等待。假如第一个线程进来发现instance为null就创建了,
等第二个线程进来的时候其实instance已经存在对象了,但是还是会进行锁等待。造成效率低。
4、将synchronized加在代码块中:
继续修改MyJvm这个类,将synchronized加在创建instance对象上
//懒汉式的单例类
class
MyJvm{
private
static
MyJvm instance =
null
;
private
MyJvm(){}
public
static
MyJvm getInstance(){
synchronized
(MyJvm.
class
){
////静态方法里没有this,所以只能锁定类的字节码信息
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
}
}
如果就像上面这样把getInstance()方法中的全部代码都使用synchronized锁住的话,同样会有和第3步(给单例加锁:直接加在方法上)一样的效率低的问题。即使instance已经初始化了,后进来的线程还是会锁等待。
所以,继续改进。加入双重检索(double checking)的方式
//懒汉式的单例类
class
MyJvm{
private
static
MyJvm instance =
null
;
private
MyJvm(){}
public
static
MyJvm getInstance(){
if
(instance ==
null
) {
//第1个线程进来会进入锁然后创建对象,第2个线程再走到这的时候已经不会再进入同步块不会出现锁等待了
synchronized
(MyJvm.
class
){
////静态方法里没有this,所以只能锁定类的字节码信息
if
(instance ==
null
) {
instance =
new
MyJvm();
}
}
}
return
instance;
}
}
最后再使用多线程main方法测试下:结果正确,并且效率会比上面的方法更快。
Thread-0-->创建:com.fz.Thread.syn.MyJvm@3bc257
Thread-1-->创建:com.fz.Thread.syn.MyJvm@3bc257
【这里可以在测试的时候加入开始时间和结束时间来更清楚的看到执行效率】
完整代码如下:
public
class
SynDemo3 {
public
static
void
main(String[] args) {
MyJvmThread thread1 =
new
MyJvmThread();
MyJvmThread thread2 =
new
MyJvmThread();
thread1.start();
thread2.start();
}
}
//懒汉式的单例类
class
MyJvm{
private
static
MyJvm instance =
null
;
private
MyJvm(){}
//双重检索方式:效率高,第一次访问需要锁等待。之后的就直接获取了
public
static
MyJvm getInstance(){
if
(instance ==
null
) {
synchronized
(MyJvm.
class
){
//静态方法里没有this,所以只能锁定类的字节码信息
if
(instance ==
null
) {
instance =
new
MyJvm();
}
}
}
return
instance;
}
//synchronized代码块范围太大:效率低,每个访问的对象都需要进行锁等待
public
static
MyJvm getInstance3(){
synchronized
(MyJvm.
class
){
//静态方法里没有this,所以只能锁定类的字节码信息
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
}
//将synchronized加在方法上:效率低,每个访问的对象都需要进行锁等待
public
static
synchronized
MyJvm getInstance2(){
//这里在方法上直接加上synchronized
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
//普通获取:线程不安全
public
static
MyJvm getInstance1(){
if
(instance ==
null
) {
instance =
new
MyJvm();
}
return
instance;
}
}
//多线程类
class
MyJvmThread
extends
Thread{
@Override
public
void
run() {
System.out.println(Thread.currentThread().getName()+
"-->创建:"
+MyJvm.getInstance());
}
}
- 线程的同步之Synchronized在单例模式中的应用
- synchronized 在单例singleton模式中的应用
- volatile与synchronized在Java单例模式中的应用
- 同步在单例设计模式中的应用
- php在设计模式中的应用之单例模式
- Java学习之线程锁--单例模式写法--synchronized
- Java学习之线程锁--单例模式--synchronized
- Java学习之线程锁--单例模式写法--synchronized
- 单例模式(Singleton)的同步锁synchronized
- 单例模式(Singleton)的同步锁synchronized
- 单例模式(懒汉模式)中的线程同步问题
- 多线程中的同步之synchronized应用——synchronized方法
- 线程的同步之Synchronized的使用
- 单例模式在DRP中的应用
- 单例模式在JAVA中的应用
- 单例模式在Unity中的应用
- 单例模式在android中的应用
- 单例模式在Unity中的应用
- Java23种设计模式学习笔记【目录总贴】
- 线程的基本概念
- 线程的状态和常用操作
- 线程的优先级
- 线程的同步之Synchronized的使用
- 线程的同步之Synchronized在单例模式中的应用
- 线程的死锁
- Maven入门-1.介绍及搭建开发环境
- Hadoop的概念、版本、发展史
- 将博客搬至CSDN
- Hadoop生态系统介绍
- Hadoop1.x HDFS系统架构
- Maven全面教程总结
- 欢迎使用CSDN-markdown编辑器