2013-09-08 4 views
2

Допустим, у вас есть:Синхронизирован «глубоко» в java?

public class Foo { 
    public Bar b; 
} 
public class Bar { 
    public int x; 
    public int y; 
} 

И тогда вы звоните:

Foo f = new Foo(); 
.... 
synchronized(f) { 
    f.b.x = 3; 
    f.b.y = 5; //x and y must be adjacent primes at all times. 
} 

Если наш поток-безопасность глубоко? то есть синхронизируется (f) предотвращает другой поток (внутри собственного синхронизированного (f) блока) от просмотра f.b, а f.b обновляется? Как насчет использования синхронизированного (этого) вместо этого?

ответ

6

Вопрос о том, является ли синхронизация «глубокой», показывает, что вы еще не полностью понимаете, как работает «синхронизация» потока Java. Все начинающие Java-программисты обычно имеют одно и то же заблуждение: «синхронизация по f делает доступ к полям f« потокобезопасными ». Это не true.

Когда один поток выполняет ваш блок synchronized(f), ни один другой поток не может вводить какой-либо блок или метод synchronized на том же объекте. ЭТО ВСЕ.

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

И, наоборот, синхронизация на f НЕ означает, что ваш доступ к полям f обязательно должен быть потокобезопасным. У вас может быть какой-то другой код в другом месте программы, изменяя поля f без какой-либо синхронизации или синхронизируя на другом объекте.

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

+0

Почему это был плохой выбор? (Любопытно). в кратком объяснении, которое будет вписываться в комментарий, я бы предложил указать на похожий язык или библиотеку, которая сделала лучший выбор. PS: Надеемся, вы знаете о последних и самых больших функциях параллелизма в Java. 'synchronized' довольно архаичен. – necromancer

+0

Я думаю, вы, вероятно, имеете в виду выбор, позволяющий использовать любые и все объекты в качестве блокировок для любого произвольного кода в дополнение к любой основной функции объекта в программе. – necromancer

+2

@randomstring, было бы лучше использовать явные объекты mutex с самого начала, например, класс Ruby's 'Mutex'. Это было бы гораздо менее запутанным, и реализациям Java не пришлось бы выбирать между высокой степенью блокировки и низким объемом памяти для каждого объекта. По-прежнему можно было бы использовать «синхронизированные» методы, если это было необходимо - это был бы просто синтаксический сахар для блокировки/разблокировки объекта Mutex, хранящегося в закрытом поле. –

6

Совсем нет.

Ключевое слово synchronized влияет только на другие синхронизированные блоки вокруг одного и того же объекта.
Это не имеет никакого отношения к самому объекту.

+0

Да, извините, изменил вопрос, чтобы прояснить эту проблему. –

+0

@KevinKostlan: Другие потоки внутри 'synchronized (f)' будут ждать завершения текущего блока, независимо от того, что он делает. Нити, не входящие в 'synchronized (f)', вообще не затрагиваются. – SLaks