2016-02-17 2 views
1

Рассмотрим следующий пример:Несинхронизированный метод все равно может получить доступ, несмотря на блокировку объекта, почему?

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 реализует его. Есть ли причина, почему этот механизм был разработан так?

+0

Поскольку объект заблокирован только от другой синхронизации. Потому что у Java нет мониторов Бринча Хансена. Потому что именно так они его и разработали. – EJP

ответ

1

Когда нить приобретает замок, его намерение приобретает эксклюзивность над объектом и интуитивно среда выполнения должна предотвратить любое изменение состояния других потоков..

Небольшая коррекция:

Когда нить приобретает замок, его намерение получает исключительные права на монитор объекта и интуитивно среды выполнения должно предотвратить любое изменение состояния других потоков, которые ждут (что нужно), чтобы получить ту же блокировку. *

его полностью оставили для программиста, чтобы указать, хочет ли он некоторое поле/ресурс, чтобы быть с нами ed только после приобретение блокировки. Если у вас есть поле, к которому можно получить доступ только одним потоком, тогда ему не нужна синхронизация (получение блокировки).

Важным моментом, который следует отметить, является то, что программисту полностью предоставляется возможность синхронизировать доступ к полям на основе кодов в программе. Например, к полю можно было бы обращаться несколькими потоками в одном пути кода (который требует синхронизации) и к нему может быть доступен только один поток на другом пути. Но так как существует большая вероятность того, что оба пути кода могут быть доступны одновременно с помощью разных потоков, вы должны приобрести блокировку перед вводом любого из указанных выше путей кода.

Теперь JIT может принять решение игнорировать ваши запросы блокировки (lock-elision), если он считает, что они не нужны (например, попытка блокировки локальных полей метода, которые никогда не исчезают).

Смежные вопросы