Какой способ лучше всего подходит для синхронизации потоков?
Какой из них наиболее надежный?
И в чем разница?
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()".