《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
}
慕容森
TA贡献1853条经验 获得超18个赞
你要重现以证明BUG的存在,没必要真的跑,你只要使用多线程的Debug模式,控制两个线程的执行步调,就可以重现。而真正线程安全的程序由于又锁等临界条件,你怎么控制步调也不会出错。
慕沐林林
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构造方法应该只会被执行一次,但如果你使用多线程的时候,你会发现被执行了多次。
解决方法就是加锁,或者使用饿汉式
添加回答
举报
0/150
提交
取消