Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Lock сложного объекта 
:(
    Опции темы
Grambler
Дата 20.3.2008, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 22.12.2006

Репутация: нет
Всего: нет



допустим есть сложный объект со ссылками на другие объекты
то если его поместить в lock то он будет полностью (со всеми вложенными объектами)
заблокирован от изменения другими потоками в пределах lock ? 

lock(obj)
{
    //обработка obj
}


PM MAIL   Вверх
Ctrl
Дата 20.3.2008, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 12.2.2008
Где: Tula

Репутация: 6
Всего: 7



Ты неверно понимаешь принцип работы инструкции lock. 
На самом деле она является синтаксической оберткой для вызовов Monitor.Enter(object obj) и Monitor.Exit(object obj) в рамках блоков try-finally. 
Причем данные методы принимают параметром ссылку на объект синхронизаиции.
Важно понимать что объект синхронизации - это не тот объект, доступ к которому ты защищаешь, а точка соприкосновения конкурирующих потоков. 
Попробую привести такую аналогию...
Помнишь игру, в которой все бегают вокруг стула пока музыка играет, а когда музыка прекращается, надо сесть на единственный стул. 
Так вот, обработка защищаемого объекта  - это как раз сидение на стуле и злорадное похихикивание над теми, кто не успел.
А объект синхронизации - это сам стул: с одной стороны без него нельзя, и чтобы выполнять обработку(сидеть и похихикивать) он должен быть, и кроме того он должен быть всем виден, с другой стороны самому стулу глубоко все-равно, он просто присутствует...

Вот примерный вариант использования
Код

//...
object guard = new object();
//...
// Thread1
lock(guard)
{
    //обработка obj
}
// Thread2
lock(guard)
{
    //обработка obj
}


p/s. Советую почитать Рихтера (критические секции - это как раз то, чем занимается lock).
PM MAIL ICQ   Вверх
vponomarov
Дата 20.3.2008, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 407
Регистрация: 11.8.2007
Где: Киев

Репутация: 4
Всего: 12



Ctrl, я тебя правильно понял: пока не завершится выполнение кода внутри блока лок все обращения к объекту будут становиться в очередь?
а что будет при попытке изменения объектов, ссылки на которые записаны в членах заблокированого объекта?


--------------------
user posted image
user posted image
PM MAIL ICQ   Вверх
ivashkanet
Дата 21.3.2008, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(vponomarov @  20.3.2008,  22:58 Найти цитируемый пост)
пока не завершится выполнение кода внутри блока лок все обращения к объекту будут становиться в очередь

Нет. Пока не завершиться выполнение блока все остальные будут ждать !в начале блока! пока он не освободиться.

Пример со стулом грамотно и наглядно  показывает, что это не так. В момент когда кто-то сидит на стуле (зашел в секцию lock (стул)) кто-то может его красить, пилить...
Если продолжать аналогию со стулом: нам нужно поменять лампочку. Для этого нужен стул. Если стульев много, то лампочку может закрутить любой, попутно мешая другому. А если он один, то приходиться ждать его, пока не остановится.

И еще раз:
Цитата(Ctrl @  20.3.2008,  20:07 Найти цитируемый пост)
Важно понимать что объект синхронизации - это не тот объект, доступ к которому ты защищаешь, а точка соприкосновения конкурирующих потоков. 

PM MAIL WWW ICQ   Вверх
Grambler
Дата 21.3.2008, 10:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 22.12.2006

Репутация: нет
Всего: нет



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

lock(guard)
{
    //обработка obj
}

но если во втором потоке опустить lock то блокировке наступает конец

вот пример в котором все работает как надо
Код

private ClassThredLock c = new ClassThredLock();
        object guard = new object();

        public void Calc()
        {
            while (true)
            {                
                lock (guard)
                {
                    c.objB.B = 3;    
                    float res = c.objA.A / c.objB.B;                    
                }
                Thread.Sleep(1);
            }
        }

        private void Set0()
        {
            while (true)
            {
                lock (guard)
                {
                    c.objB.B = 0;
                }
                Thread.Sleep(1);
            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {            
            Thread thread = new Thread(Calc);
            thread.Name = "Calc";
            thread.Start();
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {           
            Thread thread = new Thread(Set0);
            thread.Name = "Set0";
            thread.Start();
        }


но если в Set0() закоментить lock, то сразу вылетает "Попытка деления на нуль."
Код

private void Set0()
        {
            while (true)
            {
               //lock (guard)
                //{
                    c.objB.B = 0;
                //}
                Thread.Sleep(1);
            }
        }


на самом деле задача у меня следующая
есть объект, который редактируется в Propertygrid
запускается поток который его должен подрючить, 
во время вздрючки в потоке объект должен быть заблокирован от
изменений в Propertygrid

Добавлено через 5 минут и 23 секунды
Цитата(ivashkanet @  21.3.2008,  09:51 Найти цитируемый пост)
И еще раз:
Цитата(Ctrl @  20.3.2008,  20:07 Найти цитируемый пост)
Важно понимать что объект синхронизации - это не тот объект, доступ к которому ты защищаешь, а точка соприкосновения конкурирующих потоков. 

как тогда защитить доступ к объекту на время выполнения метода ?

PM MAIL   Вверх
ivashkanet
Дата 21.3.2008, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(Grambler @  21.3.2008,  09:01 Найти цитируемый пост)
как тогда защитить доступ к объекту на время выполнения метода ?

Каждую критическую секцию оборачивать в СВОЙ lock!


Код

class SomeClass
{
    object _syncRoot = new Object();

    public void SomeMethod1()
    {
        lock(syncRoot )
        {
            //обработка совместных ресурсов класса SomeClass
        }
    }

    public void SomeMethod2()
    {
        lock(syncRoot )
        {
            //обработка совместных ресурсов класса SomeClass
        }
    }


    public void SomeMethod3()
    {
        lock(syncRoot )
        {
            //обработка совместных ресурсов класса SomeClass
        }
    }
}

PM MAIL WWW ICQ   Вверх
Grambler
Дата 21.3.2008, 13:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 22.12.2006

Репутация: нет
Всего: нет



Цитата(ivashkanet @  21.3.2008,  10:47 Найти цитируемый пост)
Цитата(Grambler @  21.3.2008,  09:01 Найти цитируемый пост)
как тогда защитить доступ к объекту на время выполнения метода ?

Каждую критическую секцию оборачивать в СВОЙ lock!


ivashkanet,  а как быть с такой задачей ?

Цитата(Grambler @  21.3.2008,  10:01 Найти цитируемый пост)
на самом деле задача у меня следующая
есть объект, который редактируется в Propertygrid
запускается поток который его должен подрючить, 
во время вздрючки в потоке объект должен быть заблокирован от
изменений в Propertygrid


 у меня есть только одна идея:
перед запуском потока обработки объекта клонировать его,
т.к. это происходит в одном потоке GUI то пользователь не сможет его
поменять через  Propertygrid в момент клонирования. Поток уже будет работать с клоном
PM MAIL   Вверх
ivashkanet
Дата 21.3.2008, 13:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Цитата(Grambler @  21.3.2008,  12:07 Найти цитируемый пост)
Поток уже будет работать с клоном 

Неплохой и самый быстрый, в плане разработки, вариант.

Цитата(Grambler @  21.3.2008,  12:07 Найти цитируемый пост)
есть объект

Если объект твой, то можно создать его синхронизированную версию объекта и ложить в грид именно ее.
PM MAIL WWW ICQ   Вверх
Grambler
Дата 21.3.2008, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 53
Регистрация: 22.12.2006

Репутация: нет
Всего: нет



Цитата(ivashkanet @  21.3.2008,  13:18 Найти цитируемый пост)
Если объект твой, то можно создать его синхронизированную версию объекта и ложить в грид именно ее.

 ты имеешь ввиду [Synchronization] атрибут для класса объекта ?

PM MAIL   Вверх
ivashkanet
Дата 21.3.2008, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Grambler, нет, я имею ввиду класс-декортатор как это сделано для ArrayList:
Код

[Serializable]
private class SyncArrayList : ArrayList
{
    // Fields
    private ArrayList _list;
    private object _root;

    // Methods
    internal SyncArrayList(ArrayList list) : base(false)
    {
        this._list = list;
        this._root = list.SyncRoot;
    }

    public override int Add(object value)
    {
        lock (this._root)
        {
            return this._list.Add(value);
        }
    }

    public override void AddRange(ICollection c)
    {
        lock (this._root)
        {
            this._list.AddRange(c);
        }
    }

    public override int BinarySearch(object value)
    {
        lock (this._root)
        {
            return this._list.BinarySearch(value);
        }
    }

  // и так далее каждый метод
}

PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1310 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.