单例模式(Singleton)的同步锁synchronized

前言

当两个人同时操作一条数据时会引起并发,这时候可以用synchronized锁住代码块,进行相关处理。

注:JPAUtil根据ID查询不是实时数据,可能里面有缓存。后改成DBTool 原生查询sql,才查出实时数据。

DBTool tool = new DBTool();
Record[] r = tool.executeQuery("select state from tableName where uuid='" + uuid+ "'", null);

单例模式,有“懒汉式”和“饿汉式”两种。

1、懒汉式

单例类的实例在第一次被引用时候才被初始化。

 1 public class Singleton {  
 2     private static Singleton instance=null;  
 3      
 4     private Singleton() {  
 5          
 6     }  
 7      
 8     public static Singleton getInstance(){  
 9         if (instance == null) {  
10             instance = new Singleton();  
11         }  
12          
13         return instance;  
14     }  
15 }
View Code

2、饿汉式

单例类的实例在加载的时候就被初始化。

 1 public class Singleton {  
 2     private static Singleton instance = new Singleton();  
 3      
 4     private Singleton() {  
 5          
 6     }  
 7      
 8     public static Singleton getInstance(){  
 9         return instance;  
10     }  
11 }
View Code

在单线程中,上面两种形式基本可以满足要求了,但是在多线程环境下,单例类就有可能会失效,这个时候就要对其加锁了,来确保线程安全。

对线程加锁用的synchronized关键字,这个关键字的用法主要也分为两种:

一种是加在方法名之前,形如:public synchronized void methodeName(params){……};

二是声明同步块,形如:public void methodeName(params){synchronized(this){……}};

下面是对懒汉式单例类加上线程同步的实现:

 1 public class Singleton {  
 2     private static Singleton instance=null;  
 3      
 4     private Singleton() {  
 5          
 6     }  
 7      
 8     public synchronized static Singleton getInstance(){  
 9         if (instance == null) {  
10             instance = new Singleton();  
11         }  
12          
13         return instance;  
14     }  
15 }
View Code

这种方式效率比较低,性能不是太好,不过也可以用,因为是对整个方法加上了线程同步,其实只要在new的时候考虑线程同步就行了,这种方法不推荐使用。

同步代码块:

 1 public class Singleton {  
 2     private static Singleton instance;  
 3     private final static Object syncLock = new Object();  
 4      
 5     private Singleton() {  
 6          
 7     }  
 8      
 9     public static Singleton getInstance(){  
10         if (instance == null) {  
11             synchronized (syncLock) {  
12                 if (instance == null) {  
13                     instance = new Singleton();  
14                 }  
15             }  
16         }  
17          
18         return instance;  
19     }  
20 }
View Code

synchronized同步块括号中的锁定对象是采用的一个无关的Object类实例,而不是采用this,因为getInstance是一个静态方法,在它内部不能使用未静态的或者未实例的类对象,因此也可以用下面的方法来实现:

 1 public class Singleton {  
 2     private static Singleton instance;  
 3      
 4     private Singleton() {  
 5          
 6     }  
 7      
 8     public static Singleton getInstance(){  
 9         if (instance == null) {  
10             synchronized (Singleton.class) {  
11                 if (instance == null) {  
12                     instance = new Singleton();  
13                 }  
14             }  
15         }  
16          
17         return instance;  
18     }  
19 }
View Code
posted @ 2020-11-17 16:02  天冷吃冰棍儿  阅读(516)  评论(0编辑  收藏  举报