为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

肥皂起泡泡 2019-02-28 11:18:20
《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(); } } } 但是这段代码我仍然跑不出来异常。。。。(或者有没有人能提供能证明这个问题的例子,还要能跑出结果来。。。
查看完整描述

4 回答

?
慕的地8271018

TA贡献1796条经验 获得超4个赞

应该不会重现的,因为这段会被编译器优化掉:

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
}
查看完整回答
反对 回复 2019-03-01
?
慕容森

TA贡献1853条经验 获得超18个赞

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

查看完整回答
反对 回复 2019-03-01
?
慕沐林林

TA贡献2016条经验 获得超9个赞

你代码中的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构造方法应该只会被执行一次,但如果你使用多线程的时候,你会发现被执行了多次。
解决方法就是加锁,或者使用饿汉式

查看完整回答
反对 回复 2019-03-01
?
湖上湖

TA贡献2003条经验 获得超2个赞

编辑掉。。。

查看完整回答
反对 回复 2019-03-01
  • 4 回答
  • 0 关注
  • 544 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信