Простой вопрос про lock
От: Аноним  
Дата: 14.07.09 07:45
Оценка:
Я немного запутался. Правильно, ли я понял, что если код лочит объект в одном потоке, то в этом же потоке этот же объект можно лочить сколь угодно много. ПО крайней мере код
lock(_client)
            {
                lock(_client)
                {
                    
                }
            }

работает нормально. То есть lock начнет работать, если использующий его код находится в разных потоках? По такой же схеме, как я понял работает и Monitor. Это так задумано, или я чего-то не понимаю?
Re: Простой вопрос про lock
От: Хэлкар  
Дата: 14.07.09 07:48
Оценка:
Здравствуйте, Аноним, Вы писали:

Да, можно, lock считает количество вхождений и выходов.
Re: Простой вопрос про lock
От: Nuseraro Россия  
Дата: 14.07.09 07:51
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Я немного запутался. Правильно, ли я понял, что если код лочит объект в одном потоке, то в этом же потоке этот же объект можно лочить сколь угодно много. ПО крайней мере код

А>
А>lock(_client)
А>            {
А>                lock(_client)
А>                {
                    
А>                }
А>            }
А>

А>работает нормально.
Это верно

А>То есть lock начнет работать, если использующий его код находится в разных потоках?

Этот вопрос(если это вопрос) не понятен.

А>По такой же схеме, как я понял работает и Monitor.

Да, lock это и есть Monitor.Enter + Monitor.Exit

Это так задумано, или я чего-то не понимаю?
Что именно? Я точно ничего не понимаю в Вашем вопросе
Homo Guglens
Re[2]: Простой вопрос про lock
От: Аноним  
Дата: 14.07.09 07:57
Оценка:
Здравствуйте, Nuseraro, Вы писали:

N>Здравствуйте, Аноним, Вы писали:


А>>Я немного запутался. Правильно, ли я понял, что если код лочит объект в одном потоке, то в этом же потоке этот же объект можно лочить сколь угодно много. ПО крайней мере код

А>>
А>>lock(_client)
А>>            {
А>>                lock(_client)
А>>                {
                    
А>>                }
А>>            }
А>>

А>>работает нормально.
N>Это верно

А>>То есть lock начнет работать, если использующий его код находится в разных потоках?

N>Этот вопрос(если это вопрос) не понятен.

А>>По такой же схеме, как я понял работает и Monitor.

N>Да, lock это и есть Monitor.Enter + Monitor.Exit

N>Это так задумано, или я чего-то не понимаю?

N>Что именно? Я точно ничего не понимаю в Вашем вопросе

Я всегда думал, что для lock-а все-равно в каком потоке он используется. То есть, если вызывается lock для объекта, а тот уже был залочен, то lock тупо приостанавливает выполнения потока, пока объект не освободится. То есть код выше должен вести к DeadLock-у. Так как первый лок лочит объект и второй уже не может к нему получить доступ (пока не разлочится первый), а этого не случится, так как они в одном потоке. Но судя по всему lock учитывает поток, в котором он находится.
Вопрос мой был в следующем: это нормальное поведение lock-а, что не происходит деадлока, когда один и то же объект лочится в одном потоке (последовательно)?
Re: Простой вопрос про lock
От: Аноним  
Дата: 14.07.09 08:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я немного запутался. Правильно, ли я понял, что если код лочит объект в одном потоке, то в этом же потоке этот же объект можно лочить сколь угодно много. ПО крайней мере код

А>
А>lock(_client)
А>            {
А>                lock(_client)
А>                {
                    
А>                }
А>            }
А>

А>работает нормально. То есть lock начнет работать, если использующий его код находится в разных потоках? По такой же схеме, как я понял работает и Monitor. Это так задумано, или я чего-то не понимаю?

В догонку еще такой вопрос. Как я понял, если для синхронизации всех потоков используется только один объект синхронизации (объект1), то DeadLock нельзя получить вообще никаким способом. Это так? То есть дедлок возможен только когда первый поток залочил объект1 и хочет залочить объект2, а второй поток наоборот, залочил объект2 и хочет залочить объект1.
Re[3]: Простой вопрос про lock
От: kvl_mikki Россия  
Дата: 14.07.09 10:35
Оценка: +1
Здравствуйте, <Аноним>, Вы писали:

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

А> Вопрос мой был в следующем: это нормальное поведение lock-а, что не происходит деадлока, когда один и то же объект лочится в одном потоке (последовательно)?

Абсолютно нормально. lock придумали, т.к. при паралельной работе с данными может произойти их искажение. В рамках одного потока в принципе невозможно работать с данными паралельно, а значит lock в рамках одного потока бессмысленен.
... << RSDN@Home 1.2.0 alpha 4 rev. 1089>>
Re[2]: Простой вопрос про lock
От: Smarty Россия  
Дата: 14.07.09 14:34
Оценка: :)
Здравствуйте, Аноним, Вы писали:



А> В догонку еще такой вопрос. Как я понял, если для синхронизации всех потоков используется только один объект синхронизации (объект1), то DeadLock нельзя получить вообще никаким способом.

Абсолютно верно.

А> Это так? То есть дедлок возможен только когда первый поток залочил объект1 и хочет залочить объект2, а второй поток наоборот, залочил объект2 и хочет залочить объект1.

Именно. А отсюда — мораль: договоритесь(сами с собой, с коллегами и т.д.) что мол ребята, если нам в участке кода требуется лочить объект1 И объект2 — лочим их строго в такой последовательности, и ни разу не наоборот!! После чего термин Дед-Лоцк можете спокойно забыть.
Re[2]: Простой вопрос про lock
От: Аноним  
Дата: 15.07.09 08:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А> В догонку еще такой вопрос. Как я понял, если для синхронизации всех потоков используется только один объект синхронизации (объект1), то DeadLock нельзя получить вообще никаким способом. Это так? То есть дедлок возможен только когда первый поток залочил объект1 и хочет залочить объект2, а второй поток наоборот, залочил объект2 и хочет залочить объект1.


Нет конечно. Сам по себе один объект синхронизации никаких гарантий дать не может, а описанный Вами сценарий деадлока — наиболее очевидный, но далеко не единственный. Вот упрощённый до примитивизма пример, который, однако-же, наглядно демонстрирует ёще один распространённый сценарий деадлока:
    public partial class Form1 : Form
    {
        public Form1()
        {
            MainContext = WindowsFormsSynchronizationContext.Current;
            InitializeComponent();
        }

        public volatile Int32 LockedResource;
        public static readonly object GlobalLock = new object();

        private readonly SynchronizationContext MainContext;
        private void ModifyResource(object State)
        {
            lock (GlobalLock)
            {
                LockedResource += 15;
            }
        }

        private Thread _Thr;
        private void ThreadFunc()
        {
            lock (GlobalLock)
            {
                if (LockedResource == 0)
                {
                    MainContext.Send(ModifyResource, null);
                }
                else
                {
                    LockedResource++;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            _Thr = new Thread(ThreadFunc);
            _Thr.Start();
        }
    }

Пример, повторюсь, упрощённый, но различные вариации его в более сложных видах — не редкость. Вообще, единых правил, позволяющих полностью исключить деадлоки, не существует. Есть только общеизвестные рекомендации, как свести их вероятность к минимуму, главные из которых — внимательность и аккуратность
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.