猿问

怎样提升这个多线程bug重现的几率?(java程序

《java concurrency in practice》中有一段代码如下:

class HolderPlace{
    public Holder holder;
    public void initHolder(){
        holder = new Holder(42);
    }
}

class Holder{
    private int n;

    public Holder(int n) {
        this.n = n;
    }

    public void assertSanity(){
        if(n!=n){
            throw new AssertionError("....Assertion error...");
        }
    }
}

理论上呢,也能看懂为啥线程不安全,比如如果是下边的操作:
执行HolderPlacer.holder.assertSanity的(n!=n) 的第一个n时Holder还没给n赋值呢,但是等到第二个n执行完值给赋上了,就导致了(n!=n)==true

HolderPlace place = new HolderPlace();
           new Thread(()->place.initHolder()).start();
           new Thread(()->{
               try{
                   place.holder.assertSanity();
               }catch (NullPointerException e){

               }
           }).start();

但是我想让这个bug出现,应该怎么做才能提高bug出现的概率?
总不能光让我凭理论分析。

感谢回答者

@@@@@@@@@@@@@@@@@@编辑分割线 。。。刚才给添加到评论里了@@@@@@@@@@@@@@@@

怕大家走偏了,

我是想证明真的存在“虽然构造函数已经执行完成,引用也指向了这个对象,但是,这个对象的非final域可能还未真正的赋值”

再举个例子如下:

public class Tx {
    public int n;

    public Tx(int n) {
        this.n = n;
    }
}


public class Cons {

    public static final int INIT_NUM = 100;
    public static void main(String[] args) {
        for(int i=0;i<10000;i++){
            Map m = new HashMap<>();
            new Thread(()->{m.put("a",new Tx(INIT_NUM));}).start();
            new Thread(()->{
                try {
                    Assert.assertEquals(INIT_NUM,((Tx)m.get("a")).n);
                }catch (NullPointerException e){
                    //do nothing
                }
            }).start();
        }

    }
}

但是这段代码我仍然跑不出来异常。。。。(或者有没有人能提供能证明这个问题的例子,还要能跑出结果来。。。

肥皂起泡泡
浏览 564回答 4
4回答

慕的地8271018

应该不会重现的,因为这段会被编译器优化掉: public void assertSanity() { if (n != n) { throw new AssertionError("....Assertion error..."); } } 可能优化成: public void assertSanity() { if (false) { throw new AssertionError("....Assertion error..."); } } 甚至是: public void assertSanity() { // Do Nothing }

慕容森

你要重现以证明BUG的存在,没必要真的跑,你只要使用多线程的Debug模式,控制两个线程的执行步调,就可以重现。而真正线程安全的程序由于又锁等临界条件,你怎么控制步调也不会出错。

慕沐林林

你代码中的if比较,会像楼上所说的被优化掉,从而看不到效果。多线程不安全,你可以搜索一下单例模式的懒汉式,他是标准的线程不安全。 public class Singleton { private static Singleton instance = null; private static int count =0; private Singleton(){ System.out.println(" call constructor "+ count+" times"); count++; } public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } 按照代码的设想,singleton构造方法应该只会被执行一次,但如果你使用多线程的时候,你会发现被执行了多次。解决方法就是加锁,或者使用饿汉式

湖上湖

编辑掉。。。
随时随地看视频慕课网APP

相关分类

Java
我要回答