尽管对象被锁定,非同步方法仍然可以访问,为什么?

时间:2016-02-17 05:56:17

标签: java multithreading synchronization locking

请考虑以下事项:

    class A {
    public static void main(String[] args) throws InterruptedException
    {
        final A a = new A();
        new Thread()
        {
            public void run()
            {
                a.intrudeLock();
            };
        }.start();
        Thread.sleep(1000);
        new Thread()
        {
            public void run()
            {
                a.doSomethingAfterLocking();
            };
        }.start();
    }

    synchronized void doSomethingAfterLocking() throws InterruptedException
    {
        System.out.println("aquired lock");
        Thread.sleep(10000);
        System.out.println("finished stuff");
    }

    void intrudeLock()
    {
        System.out.println("don't need object's lock");
    }
}

通过锁定机制 - 预期输出(至少在大多数情况下):

  

获得锁定   不需要对象的锁定   完成的东西

我不是在问这个输出为什么,并且理解第二个线程不需要锁定其方法调用并因此可以入侵的原因。
现在这是我的疑问 - 当一个线程获得锁定时,它的意图是获得对象的排他性,并且直观地执行环境应该阻止其他线程的任何状态改变。但这不是Java实现它的方式。是否有理由设计这种机制?

1 个答案:

答案 0 :(得分:1)

  

当一个线程获得锁定时,它的目的是获得对象的排他性,并且直观地执行环境应该   防止其他线程进行任何状态更改。

小修正:

  

当线程获得锁定时,其意图是获得排他性   对象的监视器和直观的执行环境   应该防止等待的其他线程的任何状态更改   (需要)获得相同的锁。*

它完全由程序员指定是否希望只有在获取锁之后才能使用某些字段/资源。如果您有一个只能由一个线程访问的字段,那么它不需要同步(获取锁定)。

必须注意的重点是,完全由程序员根据程序中的代码路径同步对字段的访问。例如,字段可以由一个代码路径中的多个线程访问(调用同步),并且可以仅由另一个路径中的一个线程访问。但由于很有可能两个代码路径可以被不同的线程同时访问,因此在进入上述任何代码路径之前应该获得锁定。

现在,JIT可能决定忽略你的锁定请求( lock-elision ),如果它认为它们是不必要的(比如试图锁定永远不会逃脱的方法本地字段)。