如何在实践中理解本书的Java并发示例? [英] How to understand an example of book java concurrency in practice?

查看:122
本文介绍了如何在实践中理解本书的Java并发示例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

清单3.15.如果课程未正确发布,将面临失败的风险.

Listing 3.15. Class at Risk of Failure if Not Properly Published.

public class Holder {
 private int n;
 public Holder(int n) { this.n = n; }
 public void assertSanity() {
 if (n != n)
 throw new AssertionError("This statement is false.");
 }
} 

我的第一个问题是为什么javac无法优化if (n != n)?

My first question is why javac not optimize if (n != n)?

以下是我的示例演示

public class TestSync {
    private int n;

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

    public void assertSanity() {
        if(n!=n)
            throw new AssertionError("This statement is false");
    }

    private static TestSync test;
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    if(test == null) test = new TestSync(2);
                    else test = null;
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while(true) {
                    if(test != null)
                        try {
                            test.assertSanity();
                        } catch (NullPointerException e) {

                        }
                }
            }
        }).start();
    }
}

第二个问题是我做对了吗?因为在运行演示时它不会发生任何异常.

And my second question is Did I do the right thing? Because it occurs no exception when I run the demo.

更新

1.除了我的第一个问题: javap -c TestSync.class

1.Addition to my first question: javap -c TestSync.class

public void assertSanity();
    Code:
       0: aload_0
       1: getfield      #3                  // Field n:I
       4: aload_0
       5: getfield      #3                  // Field n:I
       8: if_icmpeq     21
      11: new           #4                  // class java/lang/AssertionError
      14: dup
      15: ldc           #5                  // String This statement is false
      17: invokespecial #6                  // Method java/lang/AssertionError."<init>":(Ljava/lang/Object;)V
      20: athrow
      21: return

我认为javac会将if(n!=n)优化为if(false)并将其缩小.

I thinked javac would optimize if(n!=n) to if(false) and shrink it.

2.为什么在if(test != null)之后仍添加try{}catch(NullPointerException e)?

2.Why I still add try{}catch(NullPointerException e) after if(test != null)?

因为我认为字段test可能由if(test!=null)之后的另一个线程设置了null.

Because I think field test may be setted null by the other thread after if(test!=null).

推荐答案

首先,javac几乎永远不会优化您正在编译的代码.仅当值是编译时常量时,才需要javac来在编译时对表达式进行求值,而表达式本身形成了编译时常量,请参见

First of all, javac almost never optimizes the code, you’re compiling. Only when the values are compile-time constants, javac is required to evaluate expressions at compile-time, which itself form compile-time constants, see JLS §15.28. Constant Expressions.

但是,操作在运行时得到了优化,甚至没有线程同步措施也使优化器可以使用乐观假设,例如变量在两次读取之间不会改变.因此,由于两次读取之间的时间短,n!=n表达式以较低的可能性永远不会评估为true,并且在启动优化程序后几乎永远不会成为true.因此,不能保证表达式n!=n总是false,在实践中不太可能会遇到true.

However, operations get optimized at runtime and it is even the absence of thread synchronization measures that allows the optimizer to use optimistic assumptions, like that a variable won’t change between two reads. So the n!=n expression starts with a low likelihood of ever evaluate to true due to the short time between the reads¹ and will almost never be true after the optimizer kicked in. So while the expression n!=n is not guaranteed to be always false, it’s unlikely to ever encounter it to be true in practice.

当然,根据墨菲定律,当您尝试引发该错误时永远不会发生,但有时会在客户身上出现,但永远不可重现……

Of course, according to Murphy’s Law, it will never happen when you try to provoke that error anyway, but once in a while at the customer, but never reproducible…

¹注意,即使由于竞争条件第二个线程读取了初始0值,n!=n也只会失败,如果在随后的读取中不再再次读取初始0.

¹ Note that even if the second thread reads the initial 0 value due to the race condition, n!=n will only fail, if does not read the initial 0 again in the subsequent read.

这篇关于如何在实践中理解本书的Java并发示例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆