Interested Article - Однопоточное выполнение
breeze
- 2021-08-11
- 1
Однопоточное выполнение ( англ. Single Threaded Execution или англ. Critical Section) — параллельный шаблон проектирования , препятствующий конкурентному вызову метода, тем самым запрещая параллельное выполнение этого метода .
Мотивы
- Класс содержит методы, которые обновляют или задают значения в переменных экземпляра класса или переменных класса.
- Метод манипулирует внешними ресурсами, которые поддерживают только одну операцию в какой-то момент времени.
- Методы класса могут вызываться параллельно различными потоками.
- Не существует временного ограничения, которое требовало бы от метода немедленного выполнения, как только его вызывают.
Следствия
- + Обеспечивается безопасность потоков
- − Производительность может быть снижена
- − Возможна взаимная блокировка
Пример реализации
Пример C#
using System; using System.Threading; namespace Digital_Patterns.Concurrency.Single_Thread_Execution { /// <summary> /// Экземпляры класса <see cref="TrafficSensor"/> связаны с сенсором движения /// транспорта, который фиксирует прохождение машиной некоторого места на /// полосе движения. /// </summary> class TrafficSensor { private static Int32 mID = 0; private ITrafficObserver _observer; public Boolean IsRun { get; set; } private Int32 _id; /// <summary> /// Конструктор /// </summary> /// <param name="observer">Объект, предназначенный для оповещения о том, что сенсор /// движения транспорта, связанный с этим объектом, /// обнаруживает проходящую машину.</param> public TrafficSensor(ITrafficObserver observer) { _id = ++mID; _observer = observer; IsRun = true; new Thread(Run).Start(); } /// <summary> /// Общая логика для потока этого объекта /// </summary> private void Run() { while (IsRun) { motitorSensor(); } } private static Random mRnd = new Random(); /// <summary> /// Этом метод вызывает метод detect объекта, когда /// связанный с ним сенсор движения транспорта фиксирует /// проходящую машину /// </summary> private void motitorSensor() { //TODO Something Thread.Sleep(mRnd.Next(1000)); var msg = System.Reflection.MethodInfo.GetCurrentMethod().Name; Console.WriteLine(String.Format(@"{0} {1} +1", _id, msg)); detect(); } /// <summary> /// Этот метод вызывается методом <see cref="motitorSensor"/>, /// чтобы сообщить о прохождении транспортного средства /// наблюдателю этого объекта /// </summary> private void detect() { _observer.vehiclePassed(); } /// <summary> /// Классы должны реализовывать этот интерфейс, /// чтобы объект <see cref="TrafficSensor"/> мог сообщить им о прохождении /// машин /// </summary> public interface ITrafficObserver { /// <summary> /// Вызывается тогда, когда <see cref="TrafficSensor"/> фиксирует /// проходящее транспортное средство. /// </summary> void vehiclePassed(); } } }
using System; namespace Digital_Patterns.Concurrency.Single_Thread_Execution { /// <summary> /// Экземпляры класса <see cref="TrafficSensorController"/> хранят текущее /// общее количество машин, прошедших мимо сенсоров движения транспорта, /// связанных с экземпляром. /// </summary> class TrafficSensorController : TrafficSensor.ITrafficObserver { private Int32 _vehicleCount = 0; /// <summary> /// Этот метод вызывается в том случае, когда сенсор движения /// транспорта фиксирует прохождение машины. Он увеличивает /// значение счетчика машин на единицу. /// </summary> public void vehiclePassed() { lock (this) { ++_vehicleCount; } } /// <summary> /// Сбрасывает счетчик машин в нуль /// </summary> /// <returns></returns> public Int32 GetAndClearCount() { lock (this) { Int32 count = _vehicleCount; _vehicleCount = 0; return count; } } } }
using System; using System.Threading; namespace Digital_Patterns.Concurrency.Single_Thread_Execution { /// <summary> /// Экземпляры класса <see cref="TrafficTransmitter"/> отвечают за передачу /// занчения, определяющего количество машин, проходящих через данное место /// дороги за одну минуту. /// </summary> class TrafficTransmitter { private TrafficSensorController _conrtoller; private Thread _myThread; public Boolean IsRun { get; set; } /// <summary> /// Конструктор /// </summary> /// <param name="conrtoller">От <see cref="TrafficSensorController"/> этот объект /// будет получать значение счетчика количества прошедших /// машин</param> public TrafficTransmitter(TrafficSensorController conrtoller) { _conrtoller = conrtoller; _myThread = new Thread(Run); IsRun = true; _myThread.Start(); } /// <summary> /// Передает значение счетчика количества машин, прошедших /// за промежуток времени /// </summary> private void Run() { while (IsRun) { Thread.Sleep(10000); Transmit(_conrtoller.GetAndClearCount()); } } private void Transmit(Int32 count) { //TODO Something var msg = System.Reflection.MethodInfo.GetCurrentMethod().Name; Console.WriteLine(String.Format(@"{0} {1}", msg, count)); } } }
using System; using Digital_Patterns.Concurrency.Single_Thread_Execution; namespace Digital_Patterns { class Program { static void Main(string[] args) { var controller = new TrafficSensorController(); var transmitter = new TrafficTransmitter(controller); Console.WriteLine(@"Press any key for start, and press again for finish"); Console.ReadKey(); var sensor1 = new TrafficSensor(controller); var sensor2 = new TrafficSensor(controller); Console.ReadKey(); sensor1.IsRun = false; sensor2.IsRun = false; transmitter.IsRun = false; Console.WriteLine(); } } }
Ссылки
- Mark Grand. Patterns in Java Volume 1: A Catalog of Reusable Design Patterns Illustrated with UML (англ.) . — Wiley & Sons, 1998. — 480 p. — ISBN 0471258393 . (см. (англ.) )
breeze
- 2021-08-11
- 1