Re[10]: Конкурентный доступ к ManulaResetEvent
От: Lloyd Россия  
Дата: 17.03.08 15:27
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Мне нужно, что если метод MethodSynchronized() уже выполнятеся ОДИМ потоком, он не мог выполняться в других.

А>НО ПРИ ЭТОМ, "другие" методы, пытающиеся выхвать MethodSynchronized из других потоков, просто дождались выполнения MethodSynchronized()
А>И НЕ ЗАПУСКАЛИ его, т.е. просто сделали return.

Вот так не пойдет?
private static object _synch = new object();

private static void Test() {
    if(Monitor.TryEnter(_synch)) {
        Console.WriteLine("Start Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(1000); // DO LONG_RUNNING-CALCULATIONS
        Console.WriteLine("Finished Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);

        Monitor.Exit(_synch);
    } else {
        Console.WriteLine("Start Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
        lock(_synch) ;
        Console.WriteLine("Finish Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
    }
}
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[11]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 17.03.08 15:32
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Вот так не пойдет?

L>
L>private static object _synch = new object();

L>private static void Test() {
L>    if(Monitor.TryEnter(_synch)) {
L>        Console.WriteLine("Start Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>        Thread.Sleep(1000); // DO LONG_RUNNING-CALCULATIONS
L>        Console.WriteLine("Finished Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);

L>        Monitor.Exit(_synch);
L>    } else {
L>        Console.WriteLine("Start Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>        lock(_synch) ;
L>        Console.WriteLine("Finish Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>    }
L>}
L>


А вот это уже похоже на то что нужно. И кода совсем немного.
Надо прикинуть как это влезет в уже существующий код. Спасибо!
Re[12]: Конкурентный доступ к ManulaResetEvent
От: Lloyd Россия  
Дата: 17.03.08 15:36
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>А вот это уже похоже на то что нужно. И кода совсем немного.

А>Надо прикинуть как это влезет в уже существующий код. Спасибо!

Да не за что.

P.S. Для спасибо есть кнопка.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[12]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 18.03.08 09:01
Оценка:
Здравствуйте, Аноним, Вы писали:

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


L>>Вот так не пойдет?

L>>
L>>private static object _synch = new object();

L>>private static void Test() {
L>>    if(Monitor.TryEnter(_synch)) {
L>>        Console.WriteLine("Start Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>>        Thread.Sleep(1000); // DO LONG_RUNNING-CALCULATIONS
L>>        Console.WriteLine("Finished Calculating {0}!!!", Thread.CurrentThread.ManagedThreadId);

L>>        Monitor.Exit(_synch);
L>>    } else {
L>>        Console.WriteLine("Start Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>>        lock(_synch) ;
L>>        Console.WriteLine("Finish Waiting {0}!!!", Thread.CurrentThread.ManagedThreadId);
L>>    }
L>>}
L>>


А>А вот это уже похоже на то что нужно. И кода совсем немного.

А>Надо прикинуть как это влезет в уже существующий код. Спасибо!

Что-то вечером вчера я не туда смотрел похоже
Это решение тоже не дает нужного поведения. Ведь когда мы входим в lock, после Monitor.Exit только один поток освободится, а мне надо чтобы освободились все, которые можгут ждать.
Re[16]: Конкурентный доступ к ManulaResetEvent
От: mihailik Украина  
Дата: 21.03.08 08:33
Оценка:
M>>
M>>readonly object sync = new object();

M>>private void NeverCallMeWhileIAmRunning()
M>>{
M>> // 80%+10%+5%+3%+2%+1%
M>>}

M>>public void CallTheBloodyMethod()
M>>{
M>>    if( Monitor.TryEnter( sync ) )
     try 
M>>    {
M>>        NeverCallMeWhileIAmRunning();
M>>    }
     finally { Monitor.Leave(sync); }
M>>}
M>>
Re[17]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 08:47
Оценка:
Здравствуйте, mihailik, Вы писали:

M>>>
M>>>readonly object sync = new object();

M>>>private void NeverCallMeWhileIAmRunning()
M>>>{
M>>> // 80%+10%+5%+3%+2%+1%
M>>>}

M>>>public void CallTheBloodyMethod()
M>>>{
M>>>    if( Monitor.TryEnter( sync ) )
M>     try 
M>>>    {
M>>>        NeverCallMeWhileIAmRunning();
M>>>    }
M>     finally { Monitor.Leave(sync); }
M>>>}
M>>>


В этом варианте, если CallTheBloodyMethod будет вызван из потока в то время, когда он уже выполняется каким-либо другим потоком, этот метод просто завершится, а мне надо чтоб он дождался пока другой поток не закончит его выполнение.
Re: Конкурентный доступ к ManulaResetEvent
От: Александр Малафеев Россия http://www.meet-tech.com
Дата: 21.03.08 09:34
Оценка:
class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(ThreadProc);
            Thread t2 = new Thread(ThreadProc);
            Thread t3 = new Thread(ThreadProc);
            t1.Start();
            t2.Start();
            t3.Start();

            t1.Join();
            t2.Join();
            t3.Join();
        }

        public static object sync1 = new object();
        public static object sync2 = new object();
        public static void ThreadProc()
        {            
            if (Monitor.TryEnter(sync1))
            {
                try
                {
                    DoSmth();
                    lock (sync2)
                    {
                        Monitor.PulseAll(sync2);
                    }
                }
                finally
                {
                    Monitor.Exit(sync1);
                }

            }
            else
            {
                lock (sync2)
                {
                    Monitor.Wait(sync2);
                }
            }
        }

        public static void DoSmth()
        {
            Console.WriteLine("i'm here");
        }
    }
Re[2]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 09:55
Оценка:
Здравствуйте, Александр Малафеев, Вы писали:

[]

А вот это действительно похоже на правду
Re[13]: Конкурентный доступ к ManulaResetEvent
От: eugen1001  
Дата: 21.03.08 10:01
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Что-то вечером вчера я не туда смотрел похоже

А>Это решение тоже не дает нужного поведения. Ведь когда мы входим в lock, после Monitor.Exit только один поток освободится, а мне надо чтобы освободились все, которые можгут ждать.

Тебе имеет смысл подменять каждый раз объект синхронизации:

т.е. поток выполняющий функцию, создаёт новый объект синхронизации и назначает его в качестве текущего объекта синхронизации. Остальные потоки ожидают освобождения текущего объекта синхронизации.
После того, как функция завершена, поток сбрасывает текущий объект синхронизации в null, а затем освобождает сам объект синхронизации.

Наличие назначенного текущего объекта синхронизации есть признак того, что функция уже выполняется.
... << RSDN@Home 1.2.0 alpha rev. 775>>
Re[2]: Конкурентный доступ к ManulaResetEvent
От: GlebZ Россия  
Дата: 21.03.08 10:55
Оценка:
Здравствуйте, Александр Малафеев, Вы писали:

АМ>class Program
АМ>    {
АМ>        static void Main(string[] args)
АМ>        {
АМ>            Thread t1 = new Thread(ThreadProc);
АМ>            Thread t2 = new Thread(ThreadProc);
АМ>            Thread t3 = new Thread(ThreadProc);
АМ>            t1.Start();
АМ>            t2.Start();
АМ>            t3.Start();

АМ>            t1.Join();
АМ>            t2.Join();
АМ>            t3.Join();
АМ>        }

АМ>        public static object sync1 = new object();
АМ>        public static object sync2 = new object();
АМ>        public static void ThreadProc()
АМ>        {            
АМ>            if (Monitor.TryEnter(sync1))
АМ>            {
АМ>                try
АМ>                {
АМ>                    DoSmth();
АМ>                    lock (sync2)
АМ>                    {
АМ>                        Monitor.PulseAll(sync2);
АМ>                    }
АМ>                }
АМ>                finally
АМ>                {
АМ>                    Monitor.Exit(sync1);
АМ>                }

АМ>            }
АМ>            else
АМ>            {
//Эмулируем переключение контекста в этот момент.
                   Thread.Sleep(100);
АМ>                lock (sync2)
АМ>                {
АМ>                    Monitor.Wait(sync2);
АМ>                }
АМ>            }
АМ>        }

АМ>        public static void DoSmth()
АМ>        {
АМ>            Console.WriteLine("i'm here");
АМ>        }
АМ>    }

По логике должно зависнуть.
... << RSDN@Home 1.2.0 alpha rev. 789>>
Re[3]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 11:28
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>По логике должно зависнуть.


Не должно и не виснет..
Re[3]: Конкурентный доступ к ManulaResetEvent
От: Александр Малафеев Россия http://www.meet-tech.com
Дата: 21.03.08 11:35
Оценка:
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, Александр Малафеев, Вы писали:


Согласен,
Но тогда можно как нибуть так

 class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(ThreadProc);
            Thread t2 = new Thread(ThreadProc);
            Thread t3 = new Thread(ThreadProc);
            t1.Start();
            t2.Start();
            t3.Start();

            t1.Join();
            t2.Join();
            t3.Join();
        }

        public static object sync1 = new object();
        public static object sync2 = new object();
        public static object sync3 = new object();
        public static bool flag = false;
        public static void ThreadProc()
        {
            bool res = false;
            lock (sync3)
            {
                res = Monitor.TryEnter(sync1);
                if(res)
                    lock (sync2) 
                        flag = false;
            }

            if (res)
            {
                try
                {
                    DoSmth();                    
                }
                finally
                {
                    lock (sync2)
                    {
                        flag = true;
                        Monitor.PulseAll(sync2);
                    }
                    Monitor.Exit(sync1);
                }

            }
            else
            {
                Thread.Sleep(100);
                lock (sync2)
                {
                    if(!flag)
                        Monitor.Wait(sync2);
                }
            }
        }

        public static void DoSmth()
        {
            Thread.Sleep(100);
            Console.WriteLine("i'm here");
        }
    }
Re[4]: Конкурентный доступ к ManulaResetEvent
От: Александр Малафеев Россия http://www.meet-tech.com
Дата: 21.03.08 11:39
Оценка:
Без sync3 можно обойтись и вместо него просто заюзать sync2
Re[5]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 12:27
Оценка:
Здравствуйте, Александр Малафеев, Вы писали:

АМ>Без sync3 можно обойтись и вместо него просто заюзать sync2


Да вроде и так не виснет
Re[2]: Конкурентный доступ к ManulaResetEvent
От: GlebZ Россия  
Дата: 21.03.08 13:13
Оценка:
Здравствуйте, Александр Малафеев, Вы писали:

Мне вообще непонятен смысл данного кода. Он эквивалентен:
if (Monitor.TryEnter(sync))
try
{
  return DoSomething();
}
finally
{
  Monitor.Exit(sync)
}
return null;
... << RSDN@Home 1.2.0 alpha rev. 789>>
Re[3]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 13:32
Оценка: +1
Здравствуйте, GlebZ, Вы писали:

GZ>Здравствуйте, Александр Малафеев, Вы писали:


GZ>Мне вообще непонятен смысл данного кода. Он эквивалентен:

GZ>
GZ>if (Monitor.TryEnter(sync))
GZ>try
GZ>{
GZ>  return DoSomething();
GZ>}
GZ>finally
GZ>{
GZ>  Monitor.Exit(sync)
GZ>}
GZ>return null;

GZ>


Неа. Тот код ждет пока не завершится выполнение метода в другом потоке и потом выходит
Re[4]: Конкурентный доступ к ManulaResetEvent
От: GlebZ Россия  
Дата: 21.03.08 14:22
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Неа. Тот код ждет пока не завершится выполнение метода в другом потоке и потом выходит

Точно, понял.
... << RSDN@Home 1.2.0 alpha rev. 789>>
Re[5]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 15:01
Оценка:
Здравствуйте, GlebZ, Вы писали:

А почему ты говоришь что оно должно зависнуть?
У меня для 10000 потоков отработало нормально.
Re[6]: Конкурентный доступ к ManulaResetEvent
От: Александр Малафеев Россия http://www.meet-tech.com
Дата: 21.03.08 16:38
Оценка:
Здравствуйте, Аноним, Вы писали:

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


А>А почему ты говоришь что оно должно зависнуть?

А>У меня для 10000 потоков отработало нормально.

Там в коде реально баг, и оно может при определнных условиях зависнуть. Может быть ситуация когда поток который выполняет метод DoSmth вызвал PulseAll, но при этом остались потоки, которые еще не вызвали Wait, так вот эти потоки зависнут когда вызовут Wait (если конечно еще раз не вызвать PulseAll).
Re[7]: Конкурентный доступ к ManulaResetEvent
От: Аноним  
Дата: 21.03.08 17:07
Оценка:
Здравствуйте, Александр Малафеев, Вы писали:

АМ>Там в коде реально баг, и оно может при определнных условиях зависнуть. Может быть ситуация когда поток который выполняет метод DoSmth вызвал PulseAll, но при этом остались потоки, которые еще не вызвали Wait, так вот эти потоки зависнут когда вызовут Wait (если конечно еще раз не вызвать PulseAll).


Да, теперь вижу.
Тогда опять получается что кроме как с ManualResetEvent это не решить (хотя там тоже, как видно из первого поста не так все гладко).
Где ж 100% солюшн?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.