Java 同步(Singleton.class)和同步(obj)之间的差异
使用以下两个版本的单例类之间有什么区别 首先,我使用的是synchronized(Singleton.class) 在第二次使用同步(Obj) //第一类 公营单身人士{Java 同步(Singleton.class)和同步(obj)之间的差异,java,synchronization,thread-safety,singleton,Java,Synchronization,Thread Safety,Singleton,使用以下两个版本的单例类之间有什么区别 首先,我使用的是synchronized(Singleton.class) 在第二次使用同步(Obj) //第一类 公营单身人士{ private static Singleton obj = null; Singleton() { } public static Singleton getInstance() { synchronized(Singleton.class){ if (obj == null) {
private static Singleton obj = null;
Singleton() {
}
public static Singleton getInstance() {
synchronized(Singleton.class){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
//第二类
public class Singleton {
private static Singleton obj = null;
Singleton() {
}
public static Singleton getInstance() {
synchronized(obj){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
第二个版本尝试在
null
上同步,这将失败。synchronized
关键字尝试获取由obj
引用的对象上的锁,并且由于它最初为null
,您将获得numpointerexception第二个版本尝试在null
上同步,这将失败。synchronized
关键字尝试获取由obj
引用的对象上的锁,由于它最初为null
,您将得到一个numpointerException
主要区别在于synchronized(obj)
不起作用:第一次调用它时,obj
是null
,因此您将看到NullPointerException
另一方面,Singleton.class
永远不会为null
,因此可以使用它进行同步。但是,恶意代码可能会执行一种攻击,使您的getInstance
方法永远等待:它们所需要的只是锁定您的Singleton.class
,并在那里无限等待
针对此攻击的常见防御措施是为锁使用单独的私有静态对象,如下所示:
public class Singleton {
private static Singleton obj = null;
private static final Object syncRoot = new Object();
Singleton() {
}
public static Singleton getInstance() {
synchronized(syncRoot){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
主要区别在于synchronized(obj)
不起作用:第一次调用它时,obj
是null
,因此您将看到NullPointerException
另一方面,Singleton.class
永远不会为null
,因此可以使用它进行同步。但是,恶意代码可能会执行一种攻击,使您的getInstance
方法永远等待:它们所需要的只是锁定您的Singleton.class
,并在那里无限等待
针对此攻击的常见防御措施是为锁使用单独的私有静态对象,如下所示:
public class Singleton {
private static Singleton obj = null;
private static final Object syncRoot = new Object();
Singleton() {
}
public static Singleton getInstance() {
synchronized(syncRoot){
if (obj == null) {
obj = new Singleton();
}
}
return obj;
}
}
它们实际上是相同的,而且是一个糟糕的实现,因为obj为NULL(在您的示例中),并且代码每次调用都是单线程的。它应该使用双重检查锁
第二个应该是:
public class Singleton {
private static object syncRoot = new object();
private static Singleton obj = null
Singleton() {
}
public static Singleton getInstance() {
if ( obj == null ){
//ONLY SINGLE THREAD IF obj == null
synchronized(syncRoot){
if ( obj == null ){
obj = new Singleton();
}
}
}
return obj;
}
}
它们实际上是相同的,而且是一个糟糕的实现,因为obj为NULL(在您的示例中),并且代码每次调用都是单线程的。它应该使用双重检查锁
第二个应该是:
public class Singleton {
private static object syncRoot = new object();
private static Singleton obj = null
Singleton() {
}
public static Singleton getInstance() {
if ( obj == null ){
//ONLY SINGLE THREAD IF obj == null
synchronized(syncRoot){
if ( obj == null ){
obj = new Singleton();
}
}
}
return obj;
}
}
当您使用synchronized(Singleton.class)时,只有在第一次创建实例之前才会应用同步,并且在可能有多个线程通过代码运行的情况下才会使用同步。如果已经有一个实例可用,您的if循环将不会创建另一个实例,通过使用这种同步方式,我们减少了很多开销,因为我们知道同步类在时间/等待方面会增加开销。当您使用synchronized(Singleton.class)时只有在第一次创建实例之前,才会应用同步,当我们有可能通过代码运行多个线程时,才会使用同步。您的if循环将考虑在已有实例可用时不创建另一个实例,通过使用这种同步方式,我们减少了很多开销,因为我们知道同步类在时间/等待方面会增加开销。在第二个示例中,在null上同步没有意义,您在第二个版本中确实意识到,在第一次调用时,您将在null
上进行同步?为什么不在静态初始值设定项中初始化你的单例呢?我对多线程是新手,所以不能真正理解synchronized()的作用?我的天真理解是,当我们使用synchronized()时,我们应该输入我们想要同步的对象/变量,我在下面的帖子中看到,我们想要同步“obj”,但我们将syncRoot作为参数传递,或者将泛型对象作为参数传递。syncRoot甚至没有更改状态,也没有在块中使用。或者,即使Singleton.class也不指定要同步的对象或变量,只指定类型,那么我们如何知道要同步的块/变量r。在第二个示例中,在null上同步没有意义。在第二个版本中,您确实意识到,在第一次调用时,您将在null
上同步?为什么不在静态初始值设定项中初始化你的单例呢?我对多线程是新手,所以不能真正理解synchronized()的作用?我的天真理解是,当我们使用synchronized()时,我们应该输入我们想要同步的对象/变量,我在下面的帖子中看到,我们想要同步“obj”,但我们将syncRoot作为参数传递,或者将泛型对象作为参数传递。syncRoot甚至没有更改状态,也没有在块中使用。或者,即使Singleton.class也不指定要同步的对象或变量,只指定类型,那么我们如何知道要同步的块/变量r。我是多线程新手,因此无法真正理解synchronized(syncRoot)的作用?我天真的理解是,当我们使用synchronized()时,我们应该输入我们想要同步的对象/变量,但我看到这里我们想要同步“obj”,但我们将syncRoot作为参数传递。syncRoot甚至没有更改状态,也没有在块中使用。或者,即使Singleton.class也不指定要同步的对象或变量,只指定类型,那么我们如何知道要同步的块/变量。@Samsynchronized
construct接受对象-任何对象,并将其用作锁。我