Обобщение Singleton паттерна

  • Автор темы Автор темы NikSoft
  • Дата начала Дата начала
В моем последнем фрагменте была допущена некорректность. В критическую секцию надо включить предложение

Код:
if (_instanceNumber > 1)
{
Console.WriteLine(String.Format("No more than 2 serial ports allowed"));
}

Проблема в том, что n потоков могут выполнить вышеуказанное предложение перед тем, как образовать очередь в критическую секцию. Для этих n потоков значение _instanceNumber
будет равно нулю и следовательно будет создано n обьектов типа SerialPort, что легко проверяется следующим кодом.

Код:
using System;
using System.Threading;

namespace SerialPorts
{
sealed class SerialPort
{
static volatile int _instanceNumber;

SerialPort() { }

public static SerialPort NextInstance()
{
SerialPort serialPort = null;

if (_instanceNumber > 1)
{
Console.WriteLine(String.Format("No more than 2 serial ports allowed"));
}
else
{
lock (typeof(SerialPort))
{
_instanceNumber++;
Console.WriteLine(String.Format("Starting to work with serial port {0}", _instanceNumber));
serialPort = new SerialPort();
Thread.Sleep(500);
}						
}
return serialPort;
}
}
}

Обращение к типу SerialPort осуществляется так.

Код:
using System;
using System.Threading;

namespace SerialPorts
{
class Program
{
static void Main(string[] args)
{
ThreadStart worker1 = new ThreadStart(WorkerThreadMethod);
ThreadStart worker2 = new ThreadStart(WorkerThreadMethod);
ThreadStart worker3 = new ThreadStart(WorkerThreadMethod);
Thread t1 = new Thread(worker1);				
Thread t2 = new Thread(worker2);				
Thread t3 = new Thread(worker3);

t1.Start();
t2.Start();
t3.Start();				

Console.ReadLine();
}

public static void WorkerThreadMethod()
{
SerialPort serialPort;

serialPort = SerialPort.NextInstance();
}
}
}

Корректный вариант приводится ниже.

Код:
using System;
using System.Threading;

namespace SerialPorts
{
sealed class SerialPort
{
static volatile int _instanceNumber;

SerialPort() { }

public static SerialPort NextInstance()
{
SerialPort serialPort = null;

lock (typeof(SerialPort))
{
if (_instanceNumber > 1)
{
Console.WriteLine(String.Format("No more than 2 serial ports allowed"));
}
else
{
_instanceNumber++;
Console.WriteLine(String.Format("Starting to work with serial port {0}", _instanceNumber));
serialPort = new SerialPort();
}
}
return serialPort;
}
}
}
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!