синхронизация
От: Аноним  
Дата: 17.12.04 10:58
Оценка:
1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?

public synchronized vod f()
{
  //....(*)
}


и

public vod f()
{
  synchronized(this)
  {
  //....(*)
  }
}


2) Если я хочу положить ЧАСТЬ данных внутри функции класса под тотже мьютекс что и synchronized методах я могу использовать synchronized(this). Так?
Re: синхронизация
От: dshe  
Дата: 17.12.04 11:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


А>
А>public synchronized void f()
А>{
А>  //....(*)
А>}
А>


А>
А>public void f()
А>{
А>  synchronized(this)
А>  {
А>  //....(*)
А>  }
А>}
А>


Логически -- да. Однако они компилируются в различный байт-код.
--
Дмитро
Re: синхронизация
От: Аноним  
Дата: 17.12.04 11:21
Оценка: 5 (1)
Здравствуйте, Аноним, Вы писали:

А>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


А>
А>public synchronized vod f()
А>{
А>  //....(*)
А>}
А>


А>и


А>
А>public vod f()
А>{
А>  synchronized(this)
А>  {
А>  //....(*)
А>  }
А>}
А>


А>2) Если я хочу положить ЧАСТЬ данных внутри функции класса под тотже мьютекс что и synchronized методах я могу использовать synchronized(this). Так?



1) думаю да, за исключением static методов

The synchronized statement (§14.18) computes a reference to an object; it then attempts to perform a lock action on that object and does not proceed further until the lock action has successfully completed. (A lock action may be delayed because the rules about locks can prevent the main memory from participating until some other thread is ready to perform one or more unlock actions.) After the lock action has been performed, the body of the synchronized statement is executed. If execution of the body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same lock.

A synchronized method (§8.4.3.6) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the lock associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the lock associated with the Class object that represents the class in which the method is defined. If execution of the method's body is ever completed, either normally or abruptly, an unlock action is automatically performed on that same lock.


2) имхо да (см. выше)
Re[2]: синхронизация
От: Аноним  
Дата: 17.12.04 11:22
Оценка:
D>Логически -- да. Однако они компилируются в различный байт-код.

Ну мне не важно во что они компилируются. Т.е. я могу этим пользоваться?
Re[3]: синхронизация
От: dshe  
Дата: 17.12.04 11:36
Оценка:
Здравствуйте, Аноним, Вы писали:

D>>Логически -- да. Однако они компилируются в различный байт-код.


А>Ну мне не важно во что они компилируются. Т.е. я могу этим пользоваться?


Можешь.
--
Дмитро
Re[2]: синхронизация
От: Pan-Halt Украина coming soon
Дата: 17.12.04 13:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


А>>
А>>public synchronized vod f()
А>>{
А>>  //....(*)
А>>}
А>>


А>>и


А>>
А>>public vod f()
А>>{
А>>  synchronized(this)
А>>  {
А>>  //....(*)
А>>  }
А>>}
А>>



А>1) думаю да, за исключением static методов


для статик методов верно следующее:
public static synchronized vod f()
{
  //....(*)
}


А>>и


public static vod f()
{
  synchronized(TheClass.class)
  {
  //....(*)
  }
}
Re: синхронизация - как лучше всео делать?
От: Волк-Призрак Россия http://ghostwolf.newmail.ru
Дата: 19.12.04 13:46
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?

Эквивалентны то они эквивалентны. но
А>
А>public synchronized vod f()
А>{
А>  //....(*)
А>}
А>


не всегда подходит. особенно, если метод большой (сам посебе или активирует большое дерево вызовов. Я думаю, что

А>
А>public vod f()
А>{
А>  synchronized(this)
А>  {
А>  //....(*)
А>  }
А>}
А>


Нужно использовать там, где:
1. В действительности синхронизировать нужно контретную "усовно небольшую" операцию (1-2 оператора), а всякие там подготовку и преобразование аргументов, обработку результатов работы синхронищруемого кода, это конечно лучше в асинхронном виде делать, когда возможно.
Например если по принципу пинг-понг (запрос-немедленный_ответ) делать загрузку классов, то лучше выделить процесс собственно пиг-понга в отдельный метод. Когда соединение существет в единственном экземпляре и shared на нескоько потоков, такой метод имхо лучше объявить static.
У кого есть дельные возражения (с аргументами типа "<большинство VM это не проглотит|в спецификации есть <*>, изза чего "static-оптимизация" не работатает, такой трюк не работает итп, см. <список иточником или оптимальных ключевых слов поиска>"). Как говорится, discussion is opened and answers are welcome*.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re[2]: синхронизация - как лучше всео делать?
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 20.12.04 09:45
Оценка:
Здравствуйте, Волк-Призрак, Вы писали:

ВП>Например если по принципу пинг-понг (запрос-немедленный_ответ) делать загрузку классов, то лучше выделить процесс собственно пиг-понга в отдельный метод. Когда соединение существет в единственном экземпляре и shared на нескоько потоков, такой метод имхо лучше объявить static.

ВП>У кого есть дельные возражения (с аргументами типа "<большинство VM это не проглотит|в спецификации есть <*>, изза чего "static-оптимизация" не работатает, такой трюк не работает итп, см. <список иточником или оптимальных ключевых слов поиска>"). Как говорится, discussion is opened and answers are welcome*.

Вот если бы в java ключевым моментом была оптимизация кода, то я бы все равно раз десять подумал перед созданием static-метода, потому что static-метоы отбирают основные преимужества OOП — инкапсуляцию и полиморфизм. Исполняемому потоку абсолютно незачем знать колько у тебя соединений, он просто должен знать что для его работы нужно соединение. Так же ему не нужно знать как это соединение получается, он просто должен знать что для его работы нужно соединение. Вот в этом случае, когда вдруг понадобится сдлать к систме не одно соединение, а скажем, использовать пул — код рабочего потока останется неизменным, он так же должен остаться неизменным когда поменяются правила создания новыз соединений. Так что 7 раз подумай и постарайся ниразу не использовать static метод (ну за некоторыми исключениями).
ICQ #333355130
Re[3]: синхронизация - как лучше всео делать?
От: Волк-Призрак Россия http://ghostwolf.newmail.ru
Дата: 20.12.04 12:15
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Вот если бы в java ключевым моментом была оптимизация кода, то я бы все равно раз десять подумал перед созданием static-метода, потому что static-метоы отбирают основные преимужества OOП — инкапсуляцию и полиморфизм.

Насчёт инкапсуляции не думаю, просто "static-оболочка существует 1м экземпляре в любом случае в 1м экземпляре". А так то что если методы статиеские есть то это не значит, что я могу выполнить
myobject.privatevariable=newvalue;

из произвольного кода, знающео о соота классе и имеющем ссылку на myobject.
А вот насчёт полиморфихма Вы правы 123%.

L> Исполняемому потоку абсолютно незачем знать колько у тебя соединений, он просто должен знать что для его работы нужно соединение. Так же ему не нужно знать как это соединение получается, он просто должен знать что для его работы нужно соединение.

Эээ... Он же должен както себе его взять:? А то у Вас получается, что ему и знать ничего ненадо о самом способе получения соединения. Как же объект сможет использовать соединение. если он сам его берёт, но не знает, у кого?
Сейчас у меня именно так сделан класс загрузчика. Т. е. загрузчик сам создаёт Socket, берёт из него потоки, и тп итд. И сам следит, что ему делать при разрыве коннекта во время скачивания класса, итп.
Конечно, следуе логике профессионального когдинга, я должен слелать так, что соединение загрузки классов загрузчику "делегируется в конструкторе" или передаётся после создания в спецметод в виде интерфейса
public interface ClassLoaderClientConnection {

  byte[] getClassData(String classname) throws NullPointerException, SecurityException, IOException;
    void validate() throws IOException,SocketException
    void tryrepair() throws SocketException;
}

И передавать этот интерфейс в конструктор/спецметод загрузчика...
Просто в силу "физиологии клинтстких соединений" может быть только одно "соедиение данных" и одно "классовое соединение". Причём загружаемые через классовое соединение модули клиента вообще ничего не знают о каких то там BOOMClientClassLoader и прочих чудесах. Об этом знаеттолько класс Launcher, который создаёт экземпляр и устанавливает свойства моего загрузчика. А потом им загружает класс Starter, котрый методом start начинает выполнение программы.
L> Вот в этом случае, когда вдруг понадобится сдлать к систме не одно соединение, а скажем, использовать пул — код рабочего потока останется неизменным, он так же должен остаться неизменным когда поменяются правила создания новыз соединений. Так что 7 раз подумай и постарайся ниразу не использовать static метод (ну за некоторыми исключениями).
Он за пределами загрузчика и так не меняется (когда я добавляю новую экранную форму, остальной код сервера и клиента обэтом не знает, так как именна классов форм привязаны к действиям через таблицу в БД.
Я использую static методы "для оптимизации" потому что когда в силу проектных решений объект сущестыует в единственом экземпляре (что не ухудшает функционалую часть программы), я оформляю его в виде класса со статическими методами.
Потому что в статические методы не передаётся "неявный аргумент объекта". а если работа с SharedJDBCConnection идёт постоянно и интенсивно, то... хотя крохи но "наптимизировать" можно. "Курочка по зёрнышку, а убирать авгиевый курятник пришел Геракл"
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re[4]: синхронизация - как лучше всео делать?
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 20.12.04 12:44
Оценка: 1 (1)
Здравствуйте, Волк-Призрак, Вы писали:

ВП>Насчёт инкапсуляции не думаю, просто "static-оболочка существует 1м экземпляре в любом случае в 1м экземпляре". А так то что если методы статиеские есть то это не значит, что я могу выполнить

ВП>
ВП>myobject.privatevariable=newvalue;  
ВП>

ВП>из произвольного кода, знающео о соота классе и имеющем ссылку на myobject.

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

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

ВП>Конечно, следуе логике профессионального когдинга, я должен слелать так, что соединение загрузки классов загрузчику "делегируется в конструкторе" или передаётся после создания в спецметод в виде интерфейса


Точно! Помнишь принцип Голивуда "Не звоните нам, мы сами с вами свяжемся"

ВП>
ВП>public interface ClassLoaderClientConnection {

ВП>  byte[] getClassData(String classname) throws NullPointerException, SecurityException, IOException;
ВП>    void validate() throws IOException,SocketException
ВП>    void tryrepair() throws SocketException;
ВП>} 
ВП>

ВП>И передавать этот интерфейс в конструктор/спецметод загрузчика...

Типа того. Только поубирать

ВП>Я использую static методы "для оптимизации" потому что когда в силу проектных решений объект сущестыует в единственом экземпляре (что не ухудшает функционалую часть программы), я оформляю его в виде класса со статическими методами.


Заметил? Все таки объект — это объект, и будет лучше если он им и останется.

ВП>Потому что в статические методы не передаётся "неявный аргумент объекта". а если работа с SharedJDBCConnection идёт постоянно и интенсивно, то... хотя крохи но "наптимизировать" можно. "Курочка по зёрнышку, а убирать авгиевый курятник пришел Геракл"


Вот при таком подходе никакой Геракл никогда не разгребет твои конюшни
ICQ #333355130
Re[5]: синхронизация - как лучше всео делать?
От: Волк-Призрак Россия http://ghostwolf.newmail.ru
Дата: 20.12.04 13:21
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Тут я не правильно выразился. Я имел ввиду не инкапсуляцию дынных а, так сказать, инкапсуляцию реализации.

Одно сово добавил, а как поменялось вс — вот великий и могучий во всей красе.
*содрогается при мысли о языке программирования C^C, на котром пишешь, как на человеческом...*

L>Статичесие методы жестко привязаны к классам, в которых они объявлены. Статические методы нельзя привязать к абстакным интерфесам. То есть класс, пользующийся статическими методами обязан знать о классе, в которых они объявлены, вместо того что бы знать интерфес объекта, который ему нужен для получения от него (объекта) некоторой функциональности.

Ну да... я както не подумал о таких зависимостях. да и про

что открывает реализацию класса (в том числе и для клиентов функциональных классов).

я тоже не подумал...

ВП>>Конечно, следуе логике профессионального когдинга, я должен слелать так, что соединение загрузки классов загрузчику "делегируется в конструкторе" или передаётся после создания в спецметод в виде интерфейса


L>Точно! Помнишь принцип Голивуда "Не звоните нам, мы сами с вами свяжемся"

вообще то, оно у меня ассацируется со шпионами и CCCP vs NATO, а не с голивудом (в 22 года то — что будет в 52?)
ВП>>
ВП>>public interface ClassLoaderClientConnection {

ВП>>  byte[] getClassData(String classname) throws NullPointerException, SecurityException, IOException;
ВП>>    void validate() throws IOException,SocketException
ВП>>    void tryrepair() throws SocketException;
ВП>>} 
ВП>>

ВП>>И передавать этот интерфейс в конструктор/спецметод загрузчика...

L>Типа того. Только поубирать

L> Э..... Вообщето я привык писать "пуленепробиваемый код", который не знает, что он в моей тепличной программе работает, и "готов к любым неожиданностям" (вроде того что какойнибудь новый модуль Системы пишется пьяным в зюзю кодером например....) — да мало ли почему вдруг "null приедет в гости")
SecurityException и SocketException я использовал чтобы в премере не городить классы исключений. А так SecurityException превращаеются NoPermissionForClassException (это имя более ясно объясняет, что именно помешало скачать класс — сервер запретил). SocketException можно конечно "заменить на" NetworkProblemException, но и тот же SocketException можно выбрасывать независимо от реализации ("преобразовывать" TelepaticConnectionCorruptedExcetion в SocketException конструкций типа catch(Type1 err){throw new Type2(args);. ).


L>Заметил? Все таки объект — это объект, и будет лучше если он им и останется.


Мдя.... Придётся перелопатить пару классов весьма и весьма ( JDBCSharedConnection и самый "законнектенный" класс SessionsController). Ну и всё что их, центральные модули моей системы , использует, тоже перелопатить, но уже Replace In Path )

L>Вот при таком подходе никакой Геракл никогда не разгребет твои конюшни

Учтём-с...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re: синхронизация
От: aefimov Россия
Дата: 21.12.04 18:36
Оценка: -1
Здравствуйте,

А>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


Нет. Синхронизация метода блокирует метод, синхронизация this блокирует инстанс объекта.

А>2) Если я хочу положить ЧАСТЬ данных внутри функции класса под тотже мьютекс что и synchronized методах я могу использовать synchronized(this). Так?


Нет. Синхронизация происходит по средствам семафоров, в качестве которых выступают объекты JVM. Cинхронизация по this — это синхронизация по инстансу объекта класса. Именно эту синхронизацию не рекомендуется использовать, так как это блокирует доступ к объекту целиком (в синхронизированных участках кода этого объекта будет всего один тред, причем, если участков много, то это приведет к тому, что все треды будут ждать пока какойнидуть один не выйдет из какого нибудь одного блока).


Спасибо!
Re[2]: синхронизация
От: Волк-Призрак Россия http://ghostwolf.newmail.ru
Дата: 21.12.04 22:04
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте,


А>>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


A>Нет. Синхронизация метода блокирует метод, синхронизация this блокирует инстанс объекта.


Ого! Вот это настоящие принципиальные отличия....


A>Нет. Синхронизация происходит по средствам семафоров, в качестве которых выступают объекты JVM. Cинхронизация по this — это синхронизация по инстансу объекта класса. Именно эту синхронизацию не рекомендуется использовать, так как это блокирует доступ к объекту целиком (в синхронизированных участках кода этого объекта будет всего один тред, причем, если участков много, то это приведет к тому, что все треды будут ждать пока какойнидуть один не выйдет из какого нибудь одного блока).


Я использую синхронизацию по классу, чтобы организовать очередь обращений клоггеру — потоки получают временой штамп, строку и объект, пишеут в StringBuffer-ы, результат своей работы подают "на конвейер" в синхронный метод, который:
[ul]
[li]Пишет строку в файл.[/li]
[li]Пишет её в консоль[/li]
[li]Отправляет её в графический логгер (swing-компонент).[/li]
[/ul]
Если бы писать в файл например не каждый раз а 1-2 раза в секунду — это ускорит работу но об "ошибке перед крахом" инфа будет утерена...


A>Спасибо!
... << RSDN@Home 1.1.4 beta 3 rev. 185>> @@J[getWorld.ApplyCheats(unfair.Cheats.IDDQD_AND_IDKFA]
while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
Скажи .net корпорации Microsoft! (c) ghostwolf 2004
7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
Re[2]: синхронизация
От: dshe  
Дата: 22.12.04 08:21
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте,


А>>1) Привильно ли я понимаю, что следующие два куска кода эквивалентны?


A>Нет. Синхронизация метода блокирует метод, синхронизация this блокирует инстанс объекта.


А>>2) Если я хочу положить ЧАСТЬ данных внутри функции класса под тотже мьютекс что и synchronized методах я могу использовать synchronized(this). Так?


A>Нет. Синхронизация происходит по средствам семафоров, в качестве которых выступают объекты JVM. Cинхронизация по this — это синхронизация по инстансу объекта класса. Именно эту синхронизацию не рекомендуется использовать, так как это блокирует доступ к объекту целиком (в синхронизированных участках кода этого объекта будет всего один тред, причем, если участков много, то это приведет к тому, что все треды будут ждать пока какойнидуть один не выйдет из какого нибудь одного блока).


Это не верно. Некто в своем сообщении
Автор:
Дата: 17.12.04
процитировал Java Language Specification, в которой объясняется как на самом деле работают и должны работать synchronized методы. Я могу лишь дополнить его ответ цитатой из того же JLS:

8.4.3.6 synchronized Methods
These are the same locks that can be used by the synchronized statement (§14.18); thus, the code:

class Test {
    int count;
    synchronized void bump() { count++; }
    static int classCount;
    static synchronized void classBump() {
        classCount++;
    }
}

has exactly the same effect as:
class BumpTest {
    int count;
    void bump() {
        synchronized (this) {
            count++;
        }
    }
    static int classCount;
    static void classBump() {
        try {
            synchronized (Class.forName("BumpTest")) {
                classCount++;
            }
        } catch (ClassNotFoundException e) {
                ...
        }
    }
}


Если у тебя есть основания считать, что в реальности все работает не так как в описано спецификации, приведи пример, который демонстрирует эти расхождения.
--
Дмитро
Re[2]: синхронизация
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 22.12.04 09:22
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Здравствуйте,

A>Нет. Синхронизация метода блокирует метод, синхронизация this блокирует инстанс объекта.

полный бред!

8.4.3.6 synchronized Methods
A synchronized method acquires a lock (§17.1) before it executes. For a class (static) method, the lock associated with the Class object for the method's class is used. For an instance method, the lock associated with this (the object for which the method was invoked) is used.
These are the same locks that can be used by the synchronized statement (§14.18); thus, the code:

class Test {
int count;
synchronized void bump() { count++; }
static int classCount;
static synchronized void classBump() {
classCount++;
}
}

has exactly the same effect as:

class BumpTest {
int count;
void bump() {
synchronized (this) {
count++;
}
}
static int classCount;
static void classBump() {
try {
synchronized (Class.forName("BumpTest")) {
classCount++;
}
} catch (ClassNotFoundException e) {
...
}
}
}


А>>2) Если я хочу положить ЧАСТЬ данных внутри функции класса под тотже мьютекс что и synchronized методах я могу использовать synchronized(this). Так?


A>Нет. Синхронизация происходит по средствам семафоров, в качестве которых выступают объекты JVM. Cинхронизация по this — это синхронизация по инстансу объекта класса. Именно эту синхронизацию не рекомендуется использовать, так как это блокирует доступ к объекту целиком (в синхронизированных участках кода этого объекта будет всего один тред, причем, если участков много, то это приведет к тому, что все треды будут ждать пока какойнидуть один не выйдет из какого нибудь одного блока).


Больший бред чем предыдущий трудно вообразить. Но это тоже бред. Кем не рекомендуется? Ссылки. А зачем тогда вобще нужна синхронизация? Правильно, чо бы гарантировать что к объекту (а следовательно и к к его аттрибутам)одновременно может иметь доступ только один поток.

A>Спасибо!

RTFM.
ICQ #333355130
Re[3]: синхронизация
От: aefimov Россия
Дата: 22.12.04 09:30
Оценка:
Здравствуйте, dshe, Вы писали:

D>Это не верно. Некто в своем сообщении
Автор:
Дата: 17.12.04
процитировал Java Language Specification, в которой объясняется как на самом деле работают и должны работать synchronized методы. Я могу лишь дополнить его ответ цитатой из того же JLS:

D>Если у тебя есть основания считать, что в реальности все работает не так как в описано спецификации, приведи пример, который демонстрирует эти расхождения.

Да есть. В приведенных примерах они действительно эквиваленты, но что будет, если методов несколько? Об этом умолчивают, а синхронизация, тем не менее, работает уже по другому.

Другими словами, чтобы сделать синхронизацию полностью эквивалентной, нужно на каждый метод создавать специальный локер-объект, в том же контексте (статическом или нет):
private final Object fooLocker = new Object();
public synchronized void foo() {
}
public void fooTheSameSync() {
   synchronized(fooLocker) {
   }
}


private static final Object fooLocker = new Object();
public static synchronized void foo() {
}
public static void fooTheSameSync() {
   synchronized(fooLocker) {
   }
}


В вашем примере приведен один метод в классе, поэтому можно в этом конкретном случае синхронизировать единственный блок инстансом класса MyClass.class или ссылкой this. Однако, если вы будете делать тоже самое для других методов, то это заблокирует доступ к ним не так как при синхронизации методов:

public void foo1() {
   syncronized (this) {
      // Если мы тут, то ни один другой метод не вызывается
      // Из других потоков
   }
}
public void foo2() {
   syncronized (this) {
      // Если мы тут, то ни один другой метод не вызывается
      // Из других потоков
   }
}


Спасибо!
Re[3]: синхронизация
От: aefimov Россия
Дата: 22.12.04 09:44
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Больший бред чем предыдущий трудно вообразить. Но это тоже бред. Кем не рекомендуется? Ссылки. А зачем тогда вобще нужна синхронизация? Правильно, чо бы гарантировать что к объекту (а следовательно и к к его аттрибутам)одновременно может иметь доступ только один поток.


И на том спасибо. Ну это вообщем то известная вещь, ну вот человек, который написал более чем 400 инспекций для IntelliJ IDEA, Dave Griphit:
Such blocks, like synchronized methods, make it hard to track just who is locking on a given object, and make possible "denial of service" attacks on objects.
И есть специальная инспекция по этому поводу, собственно. Но если так уж настаиваете могу найти "ссылок"...

Синхронизация нужна только лишь для того, чтобы быть уверенным, что в контексте одного треда данные актуальны. Блокировка — побочное явление, которое по возможности, нужно избегать.
По поводу вашего примера из JLS — я там в предыдущем постинге написал.

Спасибо!
Re[4]: синхронизация
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 22.12.04 09:49
Оценка:
Здравствуйте, aefimov, Вы писали:

A>Другими словами, чтобы сделать синхронизацию полностью эквивалентной, нужно на каждый метод создавать специальный локер-объект, в том же A>контексте (статическом или нет):


A>Спасибо!


Еще раз!
ICQ #333355130
Re[4]: синхронизация
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 22.12.04 10:16
Оценка:
Здравствуйте, aefimov, Вы писали:

A>И на том спасибо. Ну это вообщем то известная вещь, ну вот человек, который написал более чем 400 инспекций для IntelliJ IDEA, Dave Griphit:

A>Such blocks, like synchronized methods, make it hard to track just who is locking on a given object, and make possible "denial of service" attacks on objects.
A>И есть специальная инспекция по этому поводу, собственно. Но если так уж настаиваете могу найти "ссылок"...

Ну во первых это всего лишь инспекция, которая ищет потенциальное место ошибок. Во вторых, цитируешь — цитируй полностью. А то смысл, как-то коряжется. Там написано что и synchronized(this) и synchronized метод могут привести к возникновению дедлоков. Если какой один левый поток захватит лок для такого объекта и не отпустит, что все потоки, входящие в блоки синхронизации на этом объекте окажутся заблокированы. Но ведь это не значит, что теперь необходимо отказаться от synchronized методов. Это значит, что надо просто грамотно работать с synchronized блоками.

A>Синхронизация нужна только лишь для того, чтобы быть уверенным, что в контексте одного треда данные актуальны.

Точно. То есть
1) ты при входе в synchronized блок имеешь актуальное состояние объекта (то есть состояние объекта в копии памяти потока эквивалентно состоянию объекта в глобальной копии памяти)
2) пока ты в synchronized блоке, никакой другой поток не нарушит состояние объекта в глобальной копии памяти.
3) при выходе из synchronized блока состояние объекта в глобальной копии памяти синхронизируется с состоянием объекта в локальной копии памяти потока.

A>Блокировка — побочное явление, которое по возможности, нужно избегать.


Когда синхронизируемое состояние объекта составляется из нескольких аттрибутов — блокировки не избежать.
ICQ #333355130
Re[4]: синхронизация
От: Аноним  
Дата: 22.12.04 10:17
Оценка:
A>И есть специальная инспекция по этому поводу, собственно. Но если так уж настаиваете могу найти "ссылок"...

не понял, на какую тему "ссылок"? что можно блокировать методы, а не объекты целиком?

A>Синхронизация нужна только лишь для того, чтобы быть уверенным, что в контексте одного треда данные актуальны.


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

A>Спасибо!


да собсно не за что...
Re[5]: синхронизация
От: aefimov Россия
Дата: 22.12.04 10:22
Оценка: +1
Здравствуйте, Lucker, Вы писали:

L>
  • Во-первых, метод помеченный как синхронизированный синхронизируется на объекте, которому он принадлежит, в случае instance метода (и т.д. по спецификации) а не на отдельном объекте для каждого такого метода.
    L>
  • Во-вторых, зачем синхронизировать доступ к отдельному методу? Синхронизация необходима для предотвращения одновременного доступа к объекту, что бы не нарушить инвариантность его состояния. Если для некоторого метода необходимо синхронизировать доступ к некоторому подможеству состояния объекта (читай подможеству атрибутов) нежели в остальных методах, имеет смысл подумать о "выделении класса"!
    L>[/list]

    Да, не прав я, только что проверил. Экивалентны действительно, по крайней мере на винде.
    Звиняюсь
  • Re[5]: синхронизация
    От: aefimov Россия
    Дата: 22.12.04 10:24
    Оценка:
    Здравствуйте, Lucker, Вы писали:

    L>Ну во первых это всего лишь инспекция, которая ищет потенциальное место ошибок. Во вторых, цитируешь — цитируй полностью. А то смысл, как-то коряжется. Там написано что и synchronized(this) и synchronized метод могут привести к возникновению дедлоков. Если какой один левый поток захватит лок для такого объекта и не отпустит, что все потоки, входящие в блоки синхронизации на этом объекте окажутся заблокированы. Но ведь это не значит, что теперь необходимо отказаться от synchronized методов. Это значит, что надо просто грамотно работать с synchronized блоками.


    Я про synchronized (this)...

    Спасибо
    Re[3]: синхронизация
    От: aefimov Россия
    Дата: 22.12.04 10:37
    Оценка:
    Здравствуйте, Волк-Призрак, Вы писали:

    ВП>Ого! Вот это настоящие принципиальные отличия....


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

    ВП>Я использую синхронизацию по классу, чтобы организовать очередь обращений клоггеру — потоки получают временой штамп, строку и объект, пишеут в StringBuffer-ы, результат своей работы подают "на конвейер" в синхронный метод, который:

    ВП>[ul]
    ВП>[li]Пишет строку в файл.[/li]
    ВП>[li]Пишет её в консоль[/li]
    ВП>[li]Отправляет её в графический логгер (swing-компонент).[/li]
    ВП>[/ul]
    ВП>Если бы писать в файл например не каждый раз а 1-2 раза в секунду — это ускорит работу но об "ошибке перед крахом" инфа будет утерена...

    Яб наверное использовал апендеры для Log4J для этих целей... Но вообще, идея правильная. Только я, наверное, сделал бы тред отдельный который смотрит на очередь сообщений. Берет сообщение и все апендеры, последовательно передает сообщение каждому апендеру. А каждый апендер уже фигачит это куда ему хочеться — в базу, в файл и т.д. Ну сообственно Log4J так и работает.

    Спасибо!
    Re[5]: синхронизация
    От: aefimov Россия
    Дата: 22.12.04 10:39
    Оценка:
    Здравствуйте, Аноним, Вы писали:

    А>теперь рассмотрим что происходит, если, как ты говоришь, блокировка накладывается только на один синхронизированный метод, а не на весь объект — дергаешь в потоке sync метод, и пока он выполняется другой метод из другого потока (по-твоему неважно уже sync метод или не sync, т.к. они не имеют отношения к блоку вызванного тобою метода) меняет данные объекта этого же объекта, т.е. данные для твоего потока становятся не актуальны. вывод допиши сам.


    Да, фигня какаято Меня уже наставили на путь истинный... спасибо, чето я вчера погорячился.
    Re[4]: синхронизация
    От: Волк-Призрак Россия http://ghostwolf.newmail.ru
    Дата: 23.12.04 14:42
    Оценка:
    Здравствуйте, aefimov, Вы писали:

    ВП>>Я использую синхронизацию по классу, чтобы организовать очередь обращений клоггеру — потоки получают временой штамп, строку и объект, пишеут в StringBuffer-ы, результат своей работы подают "на конвейер" в синхронный метод, который:

    ВП>>[ul]
    ВП>>[li]Пишет строку в файл.[/li]
    ВП>>[li]Пишет её в консоль[/li]
    ВП>>[li]Отправляет её в графический логгер (swing-компонент).[/li]
    ВП>>[/ul]
    ВП>>Если бы писать в файл например не каждый раз а 1-2 раза в секунду — это ускорит работу но об "ошибке перед крахом" инфа будет утерена...

    A>Яб наверное использовал апендеры для Log4J для этих целей... Но вообще, идея правильная. Только я, наверное, сделал бы тред отдельный который смотрит на очередь сообщений. Берет сообщение и все апендеры, последовательно передает сообщение каждому апендеру. А каждый апендер уже фигачит это куда ему хочеться — в базу, в файл и т.д. Ну сообственно Log4J так и работает.


    Эээ.... А какая разница, очередь чего: сообщений в конвейере, или потоков к синхронному методу? А такая, что за явной очередью надо ухаживать, появляется промежуточный шаг (взять всю очередь), и мне думается, лучше пусть ось занимается синхронизацией, чем я
    ... << RSDN@Home 1.1.4 beta 3 rev. 185>> @@J[getWorld.ApplyCheats(unfair.Cheats.IDDQD_AND_IDKFA]
    while(Life.getClass().getClassLoader()==Religion.GOD){Life.be();};
    Скажи .net корпорации Microsoft! (c) ghostwolf 2004
    7 раз поищи в стандартной библиотеке, 1 раз накодь своё.
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.