Какой способ лучше всего подходит для синхронизации потоков?

Какой из них наиболее надежный? И в чем разница?

1.

[Synchronization]
public class Person : ContextBoundObject
{
    public void Print(){
        Console.WriteLine ("Start");
        Thread.Sleep (100);
        Console.WriteLine ("END");
    }
}

2.

        private readonly object obj = new object();
        public void Print(){
            lock (obj) {
                Console.WriteLine ("Start");
                Thread.Sleep (100);
                Console.WriteLine ("END");
            }
        }

Кстати, main:

            Person a = new Person ();
            for (int i = 0; i < 10; i++) {
                new Thread (a.Print).Start ();
            }

Можно ли использовать эту двухстороннюю взаимозаменяемость?

Ответ 1

SynchronizationAttribute и ContextBoundObject - концепции .NET Remoting; они не предназначены для использования в коде общего назначения и будут работать только на полной платформе .NET(не в Windows Phone, Windows Store или Silverlight). Кроме того, это заставляет вас сделать свой класс наследованием ContextBoundObject, что может быть нежелательно.

С другой стороны, lock будет работать в любом месте и не заставит вас наследовать определенный класс; он также более мелкозернистый, так как вы можете применить его только к коду, который ему нужен, а не ко всему классу.

Поэтому, если ваш код не имеет особого отношения к удалению, я бы посоветовал использовать [Synchronization].

Ответ 2

Я бы решительно проголосовал за метод 1 по методу 2. Я задаю ваш вопрос как тип реалистичной стратегии реализации на высоком уровне.

Подумайте о методе печати как "DoMyMainObjectWorkInThisNewThread()", тогда модель, которую вы настраиваете с помощью нового Thread().Start(), будет иметь объект, выполняющий его, а затем может взаимодействовать с другими потоками с методами объекта Person, которые вы защищены в вашем классе Person.

Если вы заблокируете весь объект, у вас нет простого взаимодействия с вашим потоком на уровне класса, например, сообщения о текущем статусе.

Ваш метод "1" гарантирует вам максимальную гибкость в долгосрочной перспективе, так как вы можете использовать мьютексы или объекты, которые обеспечивают только блокировку, а затем использовать делегаты для взаимодействия с длительными процессами. (Я предполагаю, что Thread.Sleep является заполнителем для длительного процесса, который вы не контролируете.) Тогда вам не нужен атрибут класса [Синхронизация] и настроен на более свободный поточный подход.

Также ваш сценарий 2 будет стоять в очереди команд печати. Таким образом, может быть реализована концепция "TryLock" или новый метод для вашего объекта Person, такой как "IsPrinting()" или "CanPrint()".