Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Знаешь, что такое Очень Плохая Вещь? ГВ>Это вот она: СГ>>C#:
System.Monitor.Enter(this);
Здравствуйте, Дарней, Вы писали:
Д> Вот придёт кому-то в голову синхронизироваться на этом же объекте, но в другом месте и в других целях — и всё, приплыли.
Ну, дуракам закон не писан. А Вы ещё спрашивали в чём разница между обычными языками (типа C#) и языками поддерживающими парадигму активных объектов (Active Oberon, Zonnon,...). Разница в том, что залочится в C# можно на любом (чужом) объекте (быть может, на ровном месте неожиданно заработав deadlock), а в Active Oberon — только на самом себе (только на this).
Лочиться только на самом себе логически следует из объединения ООП и многопоточности:
1) Все данные инкапсулированы внутри объектов.
2) Доступ к любым данным осуществляется только с помощью методов объекта.
3) Для синхронизированного (эксклюзивного) доступа к данным используются эксклюзивные методы (т.е такие методы, блоки кода в которых залочены на this).
Здравствуйте, Сергей Губанов, Вы писали: Д>> Вот придёт кому-то в голову синхронизироваться на этом же объекте, но в другом месте и в других целях — и всё, приплыли.
СГ>Ну, дуракам закон не писан. А Вы ещё спрашивали в чём разница между обычными языками (типа C#) и языками поддерживающими парадигму активных объектов (Active Oberon, Zonnon,...). Разница в том, что залочится в C# можно на любом (чужом) объекте (быть может, на ровном месте неожиданно заработав deadlock), а в Active Oberon — только на самом себе (только на this).
И это хорошо? Вот у меня есть статический метод:
public static void M()
{
lock(_syncObj)
{
...
}
}
Ну и как с этим бороться если lock будет разрешаться только на this?
Здравствуйте, ie, Вы писали:
ie>И это хорошо? Вот у меня есть статический метод:
ie>Ну и как с этим бороться если lock будет разрешаться только на this?
Здравствуйте, marat321, Вы писали:
M>Здравствуйте, ie, Вы писали:
ie>>И это хорошо? Вот у меня есть статический метод:
ie>>Ну и как с этим бороться если lock будет разрешаться только на this?
M>В абяроне есть статические методы?
Здравствуйте, ie, Вы писали:
ie>И это хорошо? Вот у меня есть статический метод:
... ie>Ну и как с этим бороться если lock будет разрешаться только на this?
Тёмная силы сторона статическими методами завладела. Объекты активные только используй ты
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Если у класса есть статические методы, значит класс используется в роли модуля. Роль this отдаётся типу класса typeof():
Здравствуйте, marat321, Вы писали:
M>В абяроне есть статические методы?
Есть, только называются они просто обычными процедурами.
Oberon — модульная система, все процедуры расположены в модулях. Модуль играет роль объекта-синглетона. Он может инкапсулировать любые данные. Доступ к этим данным осуществляется с помощью процедур этого модуля. Процедуры могут быть эксклюзивными для этого модуля. Так что, в этом смысле (эксклюзивного доступа к данным), разница между объектом и модулем отсутствует: в методах объекта лочатся на this, в процедурах модуля лочаться на сам модуль.
Пример:
PROCEDURE DoSmth;
BEGIN{EXCLUSIVE}
...
END DoSmth;
если DoSmth — это метод объекта, то {EXCLUSIVE} — обозначает лок на this,
если DoSmth — это просто обычная процедура из модуля MyModule, то {EXCLUSIVE} — обозначает лок на MyModule.
Ха-ха-ха, из-за того что в C# разрешено блокировать не только самого себя (this или typeof(Me)), но и любого другого тоже вот такое безобразие и возникает! Если бы было разрешено блокировать только самого себя (this или typeof(Me)), всё было бы чики-пуки. Разрешение блокировать чужой объект (а не лишь самого себя), это всё равно что разрешение использовать goto — та же нелокальность последствий. Хотя нет, это даже хуже чем goto — это goto-наоборот, что-то из оперы COMING FROM
Я тут у себя на работе сочинил небольшой задачник для проведения собеседований,
вот задача как раз на тему этой ветки форума:
Задача об очереди
Напишите реализацию методов 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;
}
}
}
не торопитесь смотреть решение (оно в следующем сообщении) попробуйте сначала решить задачу самостоятельно...
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Здравствуйте, ie, Вы писали:
ie>>Ну и как с этим бороться если lock будет разрешаться только на this?
СГ>Если у класса есть статические методы, значит класс используется в роли модуля. Роль this отдаётся типу класса typeof():
Но все-таки возвращаясь к первоначальной постановке. Допустим я хочу эксклюзивно владеть объектом. Т.е. объект сам не thread-safe, но я хочу использовать его из нескольких потоков. Тогда как?
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Решение задачи об очереди
Красота! Только вот я не могу никак в вашем решении узнать, является ли очередь пустая или нет, а при попытке взять из нее что-нибудь, виснем и возможно надолго.
Собеседование заваленно
Здравствуйте, ie, Вы писали:
ie>Но все-таки возвращаясь к первоначальной постановке. Допустим я хочу эксклюзивно владеть объектом. Т.е. объект сам не thread-safe, но я хочу использовать его из нескольких потоков. Тогда как?
Обзовём этот объект словом — data.
Тогда возвращаемся обратно к основным принципам ООП объединённого с многопоточностью:
1) Все данные инкапсулированы внутри объектов.
2) Доступ к данным осуществляется только с помощью методов объекта.
3) Для синхронизированного (эксклюзивного) доступа к данным используются эксклюзивные методы.
Процесс мышления таков:
1) data — это теперь данные, надо их инкапсулировать в какой-то объект MyData.
2) Снаружи доступ к данным осуществляется только с помощью методов объекта MyData.
3) Синхронизированный доступ осуществляется эксклюзивными методами объекта MyData.
Резюме:
Написать thread-safe объект-обёртку MyData над объектом data и работать через него.
Здравствуйте, ie, Вы писали:
ie>Красота! Только вот я не могу никак в вашем решении узнать, является ли очередь пустая или нет, а при попытке взять из нее что-нибудь, виснем и возможно надолго.
Это не решение "виновато", а такое было условие задачи. Условие задачи намеренно сделано очень простым, чтобы испытуемый успел решить эту задачу (и ещё ряд других) во время собеседования не слишком при этом утомив и того кто его экзаменует.
Если бы я сформулировал её так:
public interface IQueue
{
void Enqueue (object element);
object Dequeue ();
bool IsAvailable {get;} // не пуста ли очередь?bool BlockingMode {get; set;} // снять/установить/проверить блокирующий режим.
// В случае если BlockingMode = false, то Dequeue должна выдавать исключение когда очередь пуста
// В случае если BlockingMode = true, то Dequeue должна блокировать поток до тех пор пока очередь пуста
}
то мне пришлось бы дать испытуемому чуток побольше времени, но ничего принципиально нового бы о нём я бы не узнал. Ведь если он решит первую задачу, то решит и вторую (аналогичную), так чего время зря тянуть?
Сергей Губанов wrote: > 1) *Все* данные инкапсулированы внутри объектов. > 2) Доступ к данным осуществляется *только* с помощью методов объекта. > 3) Для синхронизированного (эксклюзивного) доступа к данным используются > *эксклюзивные методы*.
Вы только что описали аппартаментную (appartament) потоковую модель COM.
Рассказать какие с ней проблемы возникают?
СГ> bool IsAvailable {get;} // не пуста ли очередь?
СГ>
Кстати, проверять пуста очередь или не пуста перед выполнением Dequeue — не очень осмысленное занятие, ведь в промежуток времени между вызовами IsAvailable и Dequeue очередь может успеть опустошить кто-то другой...
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Ха-ха-ха, из-за того что в C# разрешено блокировать не только самого себя (this или typeof(Me)), но и любого другого тоже вот такое безобразие и возникает! Если бы было разрешено блокировать только самого себя (this или typeof(Me)), всё было бы чики-пуки. Разрешение блокировать чужой объект (а не лишь самого себя), это всё равно что разрешение использовать goto — та же нелокальность последствий. Хотя нет, это даже хуже чем goto — это goto-наоборот, что-то из оперы COMING FROM