用两个锁解决单例模式的同步

05-01-14 老老猿
public class Singleton {

private static Singleton instance = null;

static int i = 0;

//建实例锁 锁命令: i++ ,所有线程都可以开锁就是: i-- 命令,

//开锁的可能需要重新锁上。只有有资格建立实例的不用重新锁,有资格建立实例的条件时第一个开锁

static int j = 0;

//监视器 当多个实例开锁时监视是否有最先开锁的

public static Singleton getInstance() {

if (instance == null && i == 0) {

//如果没有实例,并且线程被锁(就是没线程可以最先开锁)

i++;

//进门就关门

j++;

//开始监视

//“开锁-重锁” 循环过程。 最先开锁的线程可以不重锁以建实例

while (i == j) {

//循环 如果没有一个线程能最先开锁

//则此次过程失败,循环下去.

i--; //开锁

if (j == i + 1) {

//本线程最先开锁,可以不重锁

instance = new Singleton();

//建实例,不重锁

}

else {

//不是第一个开锁的,可能和其线程一起开锁,也可能落后其他线程

i++;

//重锁

}

}

}

while (instance == null) {

//已经有线程最先开锁 只是没建完实例。等待

try {

Thread.sleep(1);

}

catch (InterruptedException ex) {

}

}

return instance;

}

}

guyuanwuxin
2005-01-14 15:49
无论你怎么通过变量来解决D-LOCK都是不对的,,,,,,

老老猿
2005-01-14 16:38
我现在还看不出上面程序的毛病,但我相信死锁是绝对可以避免的.

老老猿
2005-01-14 16:46
发现问题,

if (instance == null && i == 0) {

//如果没有实例,并且线程被锁(就是没线程可以最先开锁)

i++;

//进门就关门

j++;

//开始监视

//“开锁-重锁” 循环过程。 最先开锁的线程可以不重锁以建实例

while (i == j) {

i j 开始就可能不一样大小

老老猿
2005-01-14 16:53

i++;

//进门就关门

j++;

//开始监视

while (i != j) {//保证i j 同步

try {

Thread.sleep(1);

}

catch (InterruptedException ex1) {

}

}

//“开锁-重锁” 循环过程。 最先开锁的线程可以不重锁以建实例

while (i == j)

老老猿
2005-01-15 10:22
确实是不可能实现,我无法控制 在分配开始的时候不叫i增加.

xiaodaichong
2005-01-28 16:21
徒劳

fanf
2005-01-29 01:36
Seems to me there are 2 problems:

1. I don't think operations like "instance == null" and "i++" are atomic. I haven't read the Java spec though. 老老猿, are you sure if they are atomic?

2. Two different threads may keep different copies of "instance","i" and "j" in their local buffers. Those buffers are only guaranteed to be refreshed when the thread enters and leaves a synchronized block.

youngS
2005-01-29 14:07
找找锁方面的理论看看吧。同步的关键是原子操作,i++/i--之类的操作并不是原子操作,所以这是不可行的。难道java里面没有提供同步锁?为什么要自己实现锁机制?

abayi
2005-02-04 22:25
can this to use this code.

public class Singleton

{

private static Singleton singleton=null;

private static Object lock=new Object();

public static Singleton getInstance()

{

if(singleton==null)

{

synchronized(lock)

{

if(singleton==null)

{

singleton=new Singleton();

}

}

}

}

}

xiaolongii
2005-02-25 11:03
关键synchronized这个关键字不单单有加锁的功能,

还有多线程之间通讯的作用,

也就是一个线程改变了数据以后,

另一个线程在同时可能还是只看到了老数据,

除非用了同步,所以自己来用int作同步很难实现,

而且也没必要吧。

Lada314
2005-03-20 00:51
Sigleton最好不用与多线程

要用多线程的话,就用Double-Checked Locking

eg:

class A extends B{

private static A a;

private A(){

}

private synchronized static void doSync(){

if(a==null)

a=new A();

}

public static A getInstance(){

if(a==null)

doSync();

return a;

}

}

diudiu3721
2005-06-13 12:43
你觉得这个怎样?

private static Singleton instance = new Singleton();

.....

public static final Singleton get.....{

...........

return Singleton;

}

线程安全?

猜你喜欢