2016-03-13 4 views
0

Я узнал, что для обеспечения безопасной реализации программы рекомендуется использовать методы или блоки кода synchronized. Уверенность заключается в том, как приведенный ниже фрагмент кода сделает программу безопасной для потоков? Что происходит за кулисами?Что происходит за «Синхронизированным»?

public class MyCounter 
{ 
    private int count = 0; // count starts at zero 

    public synchronized void setCount(int amount) 
    { 
     count = amount; 
    } 

    public synchronized int getCount() 
    { 
     return count; 
    } 
} 
+0

Выполнение безопасного потока кода - это не просто вопрос, связанный с «синхронизацией». Для понимания даже основ требуется учебник, который слишком длинный для этого сайта. – Raedwald

ответ

3

Сомнение как ниже фрагмент кода будет сделать программу потокобезопасной?

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

И когда поток пытается выполняет метод, который помечен как synchronized он должен получить право собственности на implicit monitor перед выполнением кода в этом методе.

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

Что происходит за кулисами?

Чтобы понять, как объект монитор, собственность, ждать набор и запись набора работают вместе, давайте ниже рисунок, который представляет собой implicit monitor, который является уникальным для каждого объекта Java. Как мы видим, есть две точки входа для получения монитора, то есть от Entry Set или от Wait Set. Для нашего обсуждения мы будем использовать поток только с Entry Set в перспективе и принять пустой Wait Set.

Java monitor entry set wait set

По мере того как поток вызывает метод synchronized его помещают в Entry Set.

  • Если нить в настоящее время не принадлежит к монитору, и никакие другие нити не ждут в установленной записи, поток становится владельцем монитора и начинает выполнение кода. Это называется активной нитью.
  • Else, если есть другой поток, который владеет монитором, текущий поток помещается в Entry set и ему придется ждать своей очереди вместе с другими уже существующими потоками в Entry Set, если таковые имеются.

В то время как текущий поток ждет в Entry Set,

  • Активный поток выпустит монитор, когда это делается с выполнением кода в синхронизированный блок. (другим способом освобождения является метод wait(), который мы будем игнорировать для нашего обсуждения)
  • Впоследствии, когда монитор свободен, потоки в наборе записей будут конкурировать за приобретение монитора, и один из них получит шанс.

ПРИМЕЧАНИЕ: Как было указано выше, для приведенного выше обсуждения, мы предположили, что нет потоков в Wait Set для простоты, чтобы держать обсуждение точки. Wait Set приходит в картину с wait() и notify() звонков.

Я предлагаю и стоит взглянуть на https://www.artima.com/insidejvm/ed2/threadsynchP.html для более подробного объяснения на мониторах, набор записей & wait set.

1

Если мы имеем Резьба1, Резьба2 и Thread3 где первые два ожидает, что выпуск и третий является один, чтобы освободить их, заказ будет идти, как это.

Резьба1 входит и называет wait()
Резьба2 входит и называет wait()
Thread3 входит и называет notifyAll()
Thread3 отделки, всегда

ожидающих потоков, однако, не имеет никакого определенного порядка.
Какой из них выполнен первым, абсолютно случайный и не имеет ничего общего с порядком, в котором они называются wait(). Тем не менее поток, вызывающий notify(All), всегда будет заканчиваться до тех пор, пока не будут продолжены ожидающие потоки.

1
public synchronized void setCount(int amount) 
{ 
     count = amount; <-- *this operation is not atomic, and hence multiple thread execution may interleave resulting in race conditions* 
} 

Два шага имеют место, когда оператор присваивания выполняется:

  1. Выражение справа от = оценивается.
  2. Результат оценки присваивается переменной слева от =.

Примечание: Методы получения и установки должны быть синхронизированы с тем же монитором, так как он также решает вопрос о visibility. Без синхронизации, если поток вызывает setter, а другой вызывает setter, не гарантируется, что второй поток увидит обновленное значение.

Visibility Demonstration