求助单例双重锁定的验证

breeze的一切 2009-08-11 12:01:53
我之前还不知道这回事,把他当作经营共享了,还好火龙果指出了错误,这里表示感谢。
帖子在这。
http://topic.csdn.net/u/20090810/11/d3fd2c2e-0682-4f65-adf2-b908971b66eb.html
为了进一步弄清这个问题,我想求一个验证程序。我写了一个:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package single;

/**
*
* @author l33187
*/
public class Single {

public static Single s = null;
public static Object lock = new Object();
private int a = 0;

private Single() {
this.a = 100;
}

public static Single getSingle() {
if (s == null) {
//synchronized (lock) {
if (s == null) {
//Single tmp = new Single();
//s = tmp;
s = new Single();
}
//}
}
return s;
}

public static void main(String[] args){
for(int i=0;i<50;i++){
Thread t = new Thread(new ThreadSingle());
t.start();
}
}

public static class ThreadSingle implements Runnable {

public void run() {
try {
int count =0;
for(int i=0;i<10;i++){//主要时混淆代码,让后续代码更多的机会并行
Thread.sleep(2);
}
if (Single.getSingle().a != 100){
System.out.println("!!!初始化失败!!!!");
}

} catch (Exception e) {
e.printStackTrace();
}
}
}
}
但是很可惜行不通,甚至不加同步,还是初始化成功的。线程数从10改到1000都没验证出失败来。
请教达人验证方法。
...全文
110 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
dengsf 2009-08-11
  • 打赏
  • 举报
回复
Single() 延长时间,如 Sleep(1000)
breeze的一切 2009-08-11
  • 打赏
  • 举报
回复
你理解错了,看看我的原贴就知道了http://topic.csdn.net/u/20090810/11/d3fd2c2e-0682-4f65-adf2-b908971b66eb.html
要验证的实际就是构造函数,文章是说,new函数将会被拆分成3个微指令的伪代码。头两个创建实例,最后一个初始化。
这个程序就是想验证,双重锁单例是无效的。
可是我怎么验证,都是有效的,连不加同步也有效。可能是操作系统问题,我没有环境,有没有大侠能在Linux或unix下也验证一下。
另外,建议达人看看原贴,这里有些东西是没有写出来的。
currenttt 2009-08-11
  • 打赏
  • 举报
回复
LZ想要验证的是在多线程下,单例只会被创建一次吧?

你这样验证应该是不对的,不管单例在线程中被创建多少次,只要调用Single.getSingle(),至少有一个Single被实例化,也就是说a的值是不是100只取决于你是否调用过构造方法,而构造方法是一定会被调用的,所以你在取得a的时候,它一定是100,不知道这么说是否清楚?我是这么理解的。

至于验证方法,我想可以在构造函数中给a一个随机数,这样应该就可以知道是否是单例了吧?或者:

public class Single {

public static Single s = null;
public static Object lock = new Object();
private static int flag = 0;
public int a = 0;

private Single() {
this.a = ++flag;
}


PS.LZ上面的代码a是private,难道真的可以通过?异或ing……
捏造的信仰 2009-08-11
  • 打赏
  • 举报
回复
双重判断的问题比较复杂,我看不懂,不过我知道 1.5 以后就没这问题了。
breeze的一切 2009-08-11
  • 打赏
  • 举报
回复
哭啊,初始化只是一瞬间,我又改进了程序,模拟初始化n次。结果还是失败~~~
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package single;

/**
*
* @author l33187
*/
public class Single {

public static Single s = null;
public static Object lock = new Object();
private String a = null;

private Single() {
this.a = new String("aa");
}

public static Single getSingle() {
if (s == null) {
//synchronized (lock) {
if (s == null) {
//Single tmp = new Single();
//s = tmp;
s = new Single();
}
//}
}
return s;
}

public static void reset() {
s = null;
}

public static void main(String[] args) throws Exception {
int count = 3;
ThreadSingle[] t = new ThreadSingle[count];
for (int i = 0; i < count; i++) {
t[i] = new ThreadSingle();
t[i].start();
}
for (int i = 0; i < 100; i++) {
waitAllFinish(t);
reset();
//再执行模拟重新初始化
for (int k = 0; k < count; k++) {
t[k].resetFinished();
}
synchronized (lock) {
lock.notifyAll();
}
}
//最后设置退出
waitAllFinish(t);
for (int k = 0; k < count; k++) {
t[k].singleOver = true;
t[k].resetFinished();
}
synchronized (lock) {
lock.notifyAll();
}
}

public static void waitAllFinish(ThreadSingle[] ts) throws Exception {
boolean singleFinished = false;
outer:
while (!singleFinished) {
Thread.sleep(100);
for (ThreadSingle t : ts) {
if (!t.isSingleFinished()) {
break outer;
}
}
singleFinished = true;
}
}

public static class ThreadSingle extends Thread {

public boolean singleFinished = false;
public boolean singleOver = false;

public boolean isSingleFinished() {
synchronized (lock) {
return this.singleFinished;
}
}

public boolean resetFinished() {
synchronized (lock) {
return singleFinished = false;
}
}

public void run() {
while (!singleOver) {
try {
synchronized (lock) {
while (singleFinished) {
lock.wait();
}
}
int count = 0;
for (int i = 0; i < 10; i++) {//主要时混淆代码,让后续代码更多的机会并行

Thread.sleep(2);
}
if (Single.getSingle().a == null) {
System.out.println("!!!初始化失败!!!!");
}
synchronized (lock) {
singleFinished = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
feishare 2009-08-11
  • 打赏
  • 举报
回复
看了一会,貌似很难,不过帮顶了!

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧