lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 08:38
Оценка:
Здравствуйте, Геннадий Васильев, Вы писали:

ГВ>Знаешь, что такое Очень Плохая Вещь?

ГВ>Это вот она:
СГ>>C#:
  System.Monitor.Enter(this);


Здравствуйте, Дарней, Вы писали:

Д> Вот придёт кому-то в голову синхронизироваться на этом же объекте, но в другом месте и в других целях — и всё, приплыли.


Ну, дуракам закон не писан. А Вы ещё спрашивали в чём разница между обычными языками (типа C#) и языками поддерживающими парадигму активных объектов (Active Oberon, Zonnon,...). Разница в том, что залочится в C# можно на любом (чужом) объекте (быть может, на ровном месте неожиданно заработав deadlock), а в Active Oberon — только на самом себе (только на this).

Лочиться только на самом себе логически следует из объединения ООП и многопоточности:
1) Все данные инкапсулированы внутри объектов.
2) Доступ к любым данным осуществляется только с помощью методов объекта.
3) Для синхронизированного (эксклюзивного) доступа к данным используются эксклюзивные методы (т.е такие методы, блоки кода в которых залочены на this).
Re: lock (this)
От: ie Россия http://ziez.blogspot.com/
Дата: 29.03.06 09:28
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:
Д>> Вот придёт кому-то в голову синхронизироваться на этом же объекте, но в другом месте и в других целях — и всё, приплыли.

СГ>Ну, дуракам закон не писан. А Вы ещё спрашивали в чём разница между обычными языками (типа C#) и языками поддерживающими парадигму активных объектов (Active Oberon, Zonnon,...). Разница в том, что залочится в C# можно на любом (чужом) объекте (быть может, на ровном месте неожиданно заработав deadlock), а в Active Oberon — только на самом себе (только на this).


И это хорошо? Вот у меня есть статический метод:
public static void M()
{
    lock(_syncObj)
    {
        ...
    }
}

Ну и как с этим бороться если lock будет разрешаться только на this?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[2]: lock (this)
От: marat321  
Дата: 29.03.06 09:33
Оценка:
Здравствуйте, ie, Вы писали:

ie>И это хорошо? Вот у меня есть статический метод:


ie>Ну и как с этим бороться если lock будет разрешаться только на this?


В абяроне есть статические методы?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
silent
Re[3]: lock (this)
От: ie Россия http://ziez.blogspot.com/
Дата: 29.03.06 09:38
Оценка:
Здравствуйте, marat321, Вы писали:

M>Здравствуйте, ie, Вы писали:


ie>>И это хорошо? Вот у меня есть статический метод:


ie>>Ну и как с этим бороться если lock будет разрешаться только на this?


M>В абяроне есть статические методы?




А вот в C# с которым приводится сравнение, есть.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[2]: lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 09:42
Оценка:
Здравствуйте, ie, Вы писали:

ie>Ну и как с этим бороться если lock будет разрешаться только на this?


Если у класса есть статические методы, значит класс используется в роли модуля. Роль this отдаётся типу класса typeof():
public sealed class MyClass
{
  private static Data data;

  public static void M ()
  {
    lock (typeof(MyClass))
    {
      //эксклюзивная работа с data
      ...
    }
  }
}
Re[2]: lock (this)
От: Oyster Украина https://github.com/devoyster
Дата: 29.03.06 09:43
Оценка: :))) :))) :)
Здравствуйте, ie, Вы писали:

ie>И это хорошо? Вот у меня есть статический метод:

...
ie>Ну и как с этим бороться если lock будет разрешаться только на this?

Тёмная силы сторона статическими методами завладела. Объекты активные только используй ты
Re[3]: lock (this)
От: Oyster Украина https://github.com/devoyster
Дата: 29.03.06 09:46
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Если у класса есть статические методы, значит класс используется в роли модуля. Роль this отдаётся типу класса typeof():


Читаем классику: A Special Dr. GUI: Don't Lock Type Objects!
Re[3]: lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 09:52
Оценка:
Здравствуйте, marat321, Вы писали:

M>В абяроне есть статические методы?


Есть, только называются они просто обычными процедурами.

Oberon — модульная система, все процедуры расположены в модулях. Модуль играет роль объекта-синглетона. Он может инкапсулировать любые данные. Доступ к этим данным осуществляется с помощью процедур этого модуля. Процедуры могут быть эксклюзивными для этого модуля. Так что, в этом смысле (эксклюзивного доступа к данным), разница между объектом и модулем отсутствует: в методах объекта лочатся на this, в процедурах модуля лочаться на сам модуль.

Пример:
PROCEDURE DoSmth;
BEGIN {EXCLUSIVE}
  ...
END DoSmth;

если DoSmth — это метод объекта, то {EXCLUSIVE} — обозначает лок на this,
если DoSmth — это просто обычная процедура из модуля MyModule, то {EXCLUSIVE} — обозначает лок на MyModule.
Re[4]: lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 10:15
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Читаем классику: A Special Dr. GUI: Don't Lock Type Objects!


Ха-ха-ха, из-за того что в C# разрешено блокировать не только самого себя (this или typeof(Me)), но и любого другого тоже вот такое безобразие и возникает! Если бы было разрешено блокировать только самого себя (this или typeof(Me)), всё было бы чики-пуки. Разрешение блокировать чужой объект (а не лишь самого себя), это всё равно что разрешение использовать goto — та же нелокальность последствий. Хотя нет, это даже хуже чем goto — это goto-наоборот, что-то из оперы COMING FROM
Re: Задача об очереди
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 10:29
Оценка:
Я тут у себя на работе сочинил небольшой задачник для проведения собеседований,
вот задача как раз на тему этой ветки форума:


Задача об очереди

Напишите реализацию методов Enqueue и Dequeue.

Указание
Для синхронизации потоков, где это нужно, используйте:
• lock (expression)
• System.Threading.Monitor.Wait (object obj);
• System.Threading.Monitor.PulseAll (object obj);

Время: 5 минут


namespace EmployeeTest
{
    public interface IQueue
    {
        void Enqueue (object element);
        object Dequeue ();
    }

    public sealed class MyQueue: IQueue
    {
        private sealed class Item
        {
            public object element;
            public Item next;
            public Item (object element)
            {
                this.element = element;
            }
        }

        private Item head;
        private Item tail;

        public void Enqueue (object element)
        {
            // Добавить элемент в хвост очереди.
            // Операция должна быть безопасна в условиях многопоточного использования.
        }

        public object Dequeue ()
        {
            // Если очередь пуста, то ждать (спать) до тех пор пока кто-то другой 
            // (из другого потока) добавит элемент в очередь.
            // Извлечь элемент из головы очереди и вернуть его из функции.
            // Операция должна быть безопасна в условиях многопоточного использования.
            return null;
        }
    }
}

не торопитесь смотреть решение (оно в следующем сообщении) попробуйте сначала решить задачу самостоятельно...
Re[2]: Решение задачи об очереди
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 10:32
Оценка:
Вот...


Решение задачи об очереди

namespace EmployeeTest
{
    public interface IQueue
    {
        void Enqueue (object element);
        object Dequeue ();
    }

    public sealed class MyQueue: IQueue
    {
        private sealed class Item
        {
            public object element;
            public Item next;
            public Item (object element)
            {
                this.element = element;
            }
        }

        private Item head;
        private Item tail;

        public void Enqueue (object element)
        {
            lock (this)
            {
                Item a = new Item(element);
                if (this.tail != null) this.tail.next = a; else this.head = a;
                this.tail = a;
                System.Threading.Monitor.PulseAll(this);
            }
        }

        public object Dequeue ()
        {
            lock (this)
            {
                while (this.head == null) System.Threading.Monitor.Wait(this);
                object r = this.head.element;
                this.head = this.head.next;
                if (this.head == null) this.tail = null;
                System.Threading.Monitor.PulseAll(this);
                return r;
            }
        }
    }
}

Re[3]: lock (this)
От: ie Россия http://ziez.blogspot.com/
Дата: 29.03.06 10:36
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Здравствуйте, ie, Вы писали:


ie>>Ну и как с этим бороться если lock будет разрешаться только на this?


СГ>Если у класса есть статические методы, значит класс используется в роли модуля. Роль this отдаётся типу класса typeof():


Но все-таки возвращаясь к первоначальной постановке. Допустим я хочу эксклюзивно владеть объектом. Т.е. объект сам не thread-safe, но я хочу использовать его из нескольких потоков. Тогда как?
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[3]: Решение задачи об очереди
От: ie Россия http://ziez.blogspot.com/
Дата: 29.03.06 10:43
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Решение задачи об очереди


Красота! Только вот я не могу никак в вашем решении узнать, является ли очередь пустая или нет, а при попытке взять из нее что-нибудь, виснем и возможно надолго.
Собеседование заваленно
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[4]: lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 10:57
Оценка:
Здравствуйте, ie, Вы писали:

ie>Но все-таки возвращаясь к первоначальной постановке. Допустим я хочу эксклюзивно владеть объектом. Т.е. объект сам не thread-safe, но я хочу использовать его из нескольких потоков. Тогда как?


Обзовём этот объект словом — data.

Тогда возвращаемся обратно к основным принципам ООП объединённого с многопоточностью:
1) Все данные инкапсулированы внутри объектов.
2) Доступ к данным осуществляется только с помощью методов объекта.
3) Для синхронизированного (эксклюзивного) доступа к данным используются эксклюзивные методы.

Процесс мышления таков:
1) data — это теперь данные, надо их инкапсулировать в какой-то объект MyData.
2) Снаружи доступ к данным осуществляется только с помощью методов объекта MyData.
3) Синхронизированный доступ осуществляется эксклюзивными методами объекта MyData.

Резюме:
Написать thread-safe объект-обёртку MyData над объектом data и работать через него.
Re: lock (this)
От: WolfHound  
Дата: 29.03.06 11:03
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

Читай до просветления
Потоковобезопасный std::vector&lt;&gt;
Автор: MTdev
Дата: 22.03.06
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Решение задачи об очереди
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 11:11
Оценка:
Здравствуйте, ie, Вы писали:

ie>Красота! Только вот я не могу никак в вашем решении узнать, является ли очередь пустая или нет, а при попытке взять из нее что-нибудь, виснем и возможно надолго.


Это не решение "виновато", а такое было условие задачи. Условие задачи намеренно сделано очень простым, чтобы испытуемый успел решить эту задачу (и ещё ряд других) во время собеседования не слишком при этом утомив и того кто его экзаменует.

Если бы я сформулировал её так:
public interface IQueue
{
  void Enqueue (object element);
  object Dequeue ();
  bool IsAvailable {get;} // не пуста ли очередь?
  bool BlockingMode {get; set;} // снять/установить/проверить блокирующий режим.
  // В случае если BlockingMode = false, то Dequeue должна выдавать исключение когда очередь пуста
  // В случае если BlockingMode = true, то Dequeue должна блокировать поток до тех пор пока очередь пуста
}

то мне пришлось бы дать испытуемому чуток побольше времени, но ничего принципиально нового бы о нём я бы не узнал. Ведь если он решит первую задачу, то решит и вторую (аналогичную), так чего время зря тянуть?
Re[5]: lock (this)
От: Cyberax Марс  
Дата: 29.03.06 11:12
Оценка:
Сергей Губанов wrote:
> 1) *Все* данные инкапсулированы внутри объектов.
> 2) Доступ к данным осуществляется *только* с помощью методов объекта.
> 3) Для синхронизированного (эксклюзивного) доступа к данным используются
> *эксклюзивные методы*.
Вы только что описали аппартаментную (appartament) потоковую модель COM.
Рассказать какие с ней проблемы возникают?
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[6]: lock (this)
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 11:18
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Рассказать какие с ней проблемы возникают?


Расскажите.
Re[5]: Решение задачи об очереди
От: Сергей Губанов Россия http://sergey-gubanov.livejournal.com/
Дата: 29.03.06 11:24
Оценка: +1
СГ>
СГ>  bool IsAvailable {get;} // не пуста ли очередь?
СГ>


Кстати, проверять пуста очередь или не пуста перед выполнением Dequeue — не очень осмысленное занятие, ведь в промежуток времени между вызовами IsAvailable и Dequeue очередь может успеть опустошить кто-то другой...
Re[5]: lock (this)
От: Oyster Украина https://github.com/devoyster
Дата: 29.03.06 11:26
Оценка:
Здравствуйте, Сергей Губанов, Вы писали:

СГ>Ха-ха-ха, из-за того что в C# разрешено блокировать не только самого себя (this или typeof(Me)), но и любого другого тоже вот такое безобразие и возникает! Если бы было разрешено блокировать только самого себя (this или typeof(Me)), всё было бы чики-пуки. Разрешение блокировать чужой объект (а не лишь самого себя), это всё равно что разрешение использовать goto — та же нелокальность последствий. Хотя нет, это даже хуже чем goto — это goto-наоборот, что-то из оперы COMING FROM


Но мы-то говорим о C#...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.