Я сейчас читаю о Intrinsic Locks and Synchronization на Oracle.com, откуда я пришел к этому конкретному примеру:Сущностных Замки и синхронизация
Синхронных заявления также полезны для улучшения параллелизма с мелкозернистой синхронизацией. Предположим, например, что класс MsLunch имеет два поля экземпляра:
c1
иc2
, которые никогда не используются вместе. Все обновления этих полей должны быть синхронизированы, но нет никаких причин помешать обновлениюc1
с обновлениемc2
- и это уменьшает параллелизм, создавая ненужную блокировку. Вместо использования синхронизированных методов или с использованием связанного с этим блокировки мы создаем два объекта исключительно для обеспечения блокировок.
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
До этого раздела, synchronized
методы, где объясняется:
public synchronized void increment() {
this.c++;
}
Какой должна быть, и, пожалуйста, поправьте меня, если я ошибаюсь, то же самое, как
public void increment() {
synchronized(this) {
c++;
}
}
если Я не добавляю функциональность в increment()
, это правильно?
Мой вопрос теперь приходит из фразы:
, но нет никаких причин, чтобы предотвратить обновление
c1
от того перемежаемого с обновлениемc2
Я не уверен, если я полностью понять, что «чередуется» означает в этом контексте. Означает ли это, что если я, например? удалить lock2
из MsLunch
Например:
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
// private Object lock2 = new Object(); // 'lock2' is no more!
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock1) { // Using 'lock1' here too
c2++;
}
}
}
я мог попасть в неприятности с блокировкой? Скажите thread-1
пробегает inc1()
, получает блокировку от lock1
, но подвешивается перед тем, как увеличить или отменить блокировку. Теперь thread-2
вводит inc2()
, где создается еще одна блокировка для lock1
. Это то, чего избегают, используя другой lock2
, и является ли это причиной того, что я бы не использовал просто в качестве шлюза-провайдера? Или другими словами: Может ли это вызвать проблему?
Нет, вы не можете попасть в * проблему *, вы просто не должны одновременно увеличивать «c1» и «c2», поскольку они имеют одну и ту же блокировку (независимо от того, является ли это «этим» или отдельный 'lock1') и поэтому имеют зависимость между ними через блокировку. – Kayaman
@ Кайаман. О, немецкий перевод «чередующихся» - это нечто вроде «друг в друга» или «друг в друга», поэтому я немного смутился. Но почему это предотвращает «c1» и «c2» одновременно? В примере 'lock1'-only, если' lock1' содержит блокировку «* где угодно» в коде, означает ли это, что он будет блокироваться и в другом месте? Поэтому 'thread-2' должен ждать' thread-1', чтобы обновить 'c1', прежде чем он сможет обновить' c2'. Это также подразумевает, что каждый объект может одновременно обеспечивать * one * lock одновременно, что мне просто не ясно было прочитать главу. – displayname
Да, каждый объект обеспечивает один замок за раз. Вот и вся идея, почему синхронизация работает так, как будто. – Kayaman