Совершенно ясно, как это?
for (key, value) in col_read {
print(key)
for (innerKey, innerValue) in value {
print(innerKey)
for number in innerValue {
print(number)
}
}
}
PS - Используйте lowerCamelCase для имен переменных, как упомянуто в Рекомендации по разработке API [ 111].
Они эквивалентны в функции, хотя компиляторы, которые я протестировал (Java 1.6.0_07 и Eclipse 3.4) генерируют другой байт-код. Первое генерирует:
// access flags 33
public synchronized someMethod()V
RETURN
Второе генерирует:
// access flags 1
public someMethod()V
ALOAD 0
DUP
MONITORENTER
MONITOREXIT
RETURN
(Благодаря ASM для печати байт-кода).
Таким образом, различие между ними сохраняется к уровню байт-кода, и это до JVM для создания их поведения тем же. Однако они действительно имеют тот же функциональный эффект - посмотрите пример в Спецификации языка Java.
Нужно отметить, что, если метод переопределяется в подклассе, что это не обязательно синхронизируется - таким образом, нет никакого различия в этом отношении также.
Я также запустил тест для блокирования доступа попытки потока монитор в каждом случае для сравнения то, на что их отслеживания стека будут похожи в дампе потока, и они оба содержали рассматриваемый метод, таким образом, нет никакого различия там также.
Я сделал исходный комментарий, что операторы идентичны.
В обоих случаях первая вещь, которая происходит, состоит в том, что вызывающий поток попытается получить текущий объект (значение, this
') монитор.
Я не знаю о другом байт-коде, я буду рад услышать различие. Но на практике, они на 100% идентичны.
Править: я собираюсь разъяснить это, поскольку некоторые люди здесь поняли его превратно. Рассмотрите:
public class A {
public synchronized void doStuff()
{
// do stuff
}
}
public class B extends A {
public void doStuff()
{
// do stuff
// THIS IS OVERRIDE!
}
}
В этом случае doStuff()
в классе B все еще переопределяет doStuff()
в классе A даже при том, что это не синхронизируется.
Синхронизируемое ключевое слово никогда не является частью контракта! Не для подклассов, не для интерфейсов, не для абстрактных классов.
Да. Используя синхронизируемое ключевое слово на использовании метода экземпляра 'это' как монитор, также с помощью него на методе класса (статический метод) использует Объект класса класса (Foo.class).
Таким образом, можно синхронизировать все методы, и в то же время, синхронизировать его с фрагментом кода в другом методе с помощью синхронизируемого стиля блока.
MyObject myObjectA;
MyObject myObjectB;
public void someMethod() {
synchronized (this) {
//stuff
}
}
public void someMethodA() {
synchronized (myObjectA) {
//stuff
}
}
public void someMethodB() {
synchronized (myObjectB) {
//stuff
}
}
В этом случае:
someMethod
блоки весь классsomeMethodA
блоки myObjectA
толькоsomeMethodB
блоки myObjectB
толькоsomeMethodA
и someMethodB
может быть вызван одновременноЯ не вижу функционального различия - оба синхронизируют их все тела метода на (этом). Как сделал человека, который прокомментировал, что они отличаются, выравнивают по ширине их оператор?
Я сделал исходный комментарий. Мой комментарий был то, что они логически эквивалентны, но компилируют в другой байт-код.
Я не добавил ничто больше для выравнивания по ширине его в то время, потому что нет очень для выравнивания по ширине действительно - они просто компилируют в другой байт-код. Если Вы объявляете метод, как синхронизируется, то та синхронизация является частью определения метода. Синхронизируемый блок в рамках метода не является частью определения метода, но вместо этого включает отдельные байт-коды, чтобы получить и выпустить монитор, поскольку один из плакатов выше проиллюстрировал. Строго говоря они - немного отличающиеся вещи, хотя к полной логике Вашей программы, они эквивалентны.
Когда это имеет значение? Ну, на самом современном настольном VMs, почти никогда. Но например: