本机方法同步 [英] Native method synchronization

查看:132
本文介绍了本机方法同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样定义的本机方法:

I have a native method method defined like this:

public static native int doSomething();

但是,此方法不是线程安全的。所以,我在其上放了一个 synchronized 关键字,所以它现在看起来像这样:

However, this method is not thread-safe. So, I put a synchronized keyword on it, so it looks like this now:

public static synchronized native int doSomething();

这似乎可以解决问题,但我不确定它是否确实存在。这有效吗?它是否实际上正确锁定了对方法的访问权限?

This appears to fix the problem, but I'm not sure if it actually does. Is this valid? Does it actually properly lock access to the method?

推荐答案

阅读相关的 JLS部分,JLS中没有任何内容禁止<$ c来自方法定义的$ c> static 和 native 。根据相关的JVM规范:

After reading the relevant JLS section, there is nothing in the JLS which prohibits static and native from being in the method definition. According to the relevant JVM spec:


方法级同步是隐式执行的,作为方法调用和返回的一部分(第2.18.8节)。同步方法在运行时常量池的method_info结构(第4.6节)中由ACC_SYNCHRONIZED标志区分,该标志由方法调用指令检查。当调用设置了ACC_SYNCHRONIZED的方法时,执行线程进入监视器,调用方法本身,并退出监视器,方法调用是正常还是突然完成。在执行线程拥有监视器期间,没有其他线程可以输入它。如果在调用synchronized方法期间抛出异常并且synchronized方法不处理异常,则在异步从同步方法中重新抛出之前,将自动退出该方法的监视器。

Method-level synchronization is performed implicitly, as part of method invocation and return (§2.11.8). A synchronized method is distinguished in the run-time constant pool's method_info structure (§4.6) by the ACC_SYNCHRONIZED flag, which is checked by the method invocation instructions. When invoking a method for which ACC_SYNCHRONIZED is set, the executing thread enters a monitor, invokes the method itself, and exits the monitor whether the method invocation completes normally or abruptly. During the time the executing thread owns the monitor, no other thread may enter it. If an exception is thrown during invocation of the synchronized method and the synchronized method does not handle the exception, the monitor for the method is automatically exited before the exception is rethrown out of the synchronized method.

因此,生成的字节码没有任何 monitorenter monitorexit 指令,作为 synchronized 块。在这种情况下,唯一生成的是 invokestatic ,以便调用静态方法。如果您调用静态本机同步方法,静态本机方法或<$ c $,则会生成此指令c> static 方法。

Because of this, the bytecode that is generated does not have any monitorenter or monitorexit instructions, as a synchronized block does. The only thing that is generated in this case is invokestatic, in order to invoke the static method. This instruction is generated if you call a static native synchronized method, a static native method, or a static method.

以下是生成字节码的示例代码:

Here's some example code with the generated bytecode:

    public static void main( String[] args ){
            doSomething1();
            System.out.println("Now do 2");
            doSomething2();
            System.out.println("native java");
            doSomethingJava();

            String s = "test";
            synchronized ( s ){
                    int x = 9 + 5;
            }
    }

    public static native void doSomething1();
    public static synchronized native void doSomething2();

    public static synchronized void doSomethingJava(){
            System.out.println("synchronized");
    }

生成的字节码:

Compiled from "test.java"
class test {
  test();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #2                  // Method doSomething1:()V
       3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       6: ldc           #4                  // String Now do 2
       8: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      11: invokestatic  #6                  // Method doSomething2:()V
      14: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      17: ldc           #7                  // String native java
      19: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      22: invokestatic  #8                  // Method doSomethingJava:()V
      25: ldc           #9                  // String test
      27: astore_1      
      28: aload_1       
      29: dup           
      30: astore_2      
      31: monitorenter  
      32: bipush        14
      34: istore_3      
      35: aload_2       
      36: monitorexit   
      37: goto          47
      40: astore        4
      42: aload_2       
      43: monitorexit   
      44: aload         4
      46: athrow        
      47: return        
    Exception table:
       from    to  target type
          32    37    40   any
          40    44    40   any

  public static native void doSomething1();

  public static synchronized native void doSomething2();

  public static synchronized void doSomethingJava();
    Code:
       0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #10                 // String synchronized
       5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return        
}

这篇关于本机方法同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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