Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по C_1.docx
Скачиваний:
3
Добавлен:
01.05.2025
Размер:
1 Мб
Скачать
☆
  1. Проблемы одновременности и синхронизации потоков. Общий доступ к данным из разных потоков, предотвращение коллизий.

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

Как избежать подобных непредсказуемых состояний? Для этого можно использовать стандартное средство — синхронизация. Синхронизация позволяет задавать критические секции (critical sections) кода, в которые в каждый отдельный момент может входить только один поток, гарантируя, что любые временные недействительные состояния объекта будут невидимы его клиентам. Имеется несколько средств определения критических секций, включая классы .NET Monitor и Mutex, а также оператор С# lock.

Формат использования инструкции lock таков:

lock(выражение) {

// Инструкции, подлежащие синхронизации.

}

Для обычных методов в качестве выражения используется указатель this, для статических – typeof(класс).

Здесь параметр выражение представляет собой ссылку на синхронизируемый объект. Если нужно синхронизировать только один элемент, фигурные скобки можно опустить. Инструкция lock гарантирует, что указанный блок кода, защищенный блокировкой для данного объекта, может быть использован только потоком, который получает эту блокировку. Все другие потоки остаются заблокированными до тех пор, пока блокировка не будет снята. А снята она будет лишь при выходе из этого блока.

  1. Синхронизация доступа к общим данным с помощью блокировок.

Задание: 1) Проанализировать процесс синхронизации посредством управления доступом к методу sumIt(), который суммирует элементы массива целочисленного типа, используя инструкцию блокировки lock(this) и без нее:

class SumArray

{ int sum; public int sumIt(int[] mas) {

//lock (this)//Блокировка всего метода //{

sum = 0;

for (int i = 0; i < mas.Length; i++)

{ sum += mas[i];

Console.WriteLine("Промежуточная сумма для потока " + Thread.CurrentThread.Name + "=" + sum);

Thread.Sleep(50); }

return sum;

//}} }//////////////////////////////////////////////////////////////////

class SThread

{public Thread Thrd; int[] array; int rezult;

//Создаем один объект класса SumArray //для всех экземпляров класса SThread (для всех потоков):

static SumArray Ob_sum = new SumArray();

//Конструктор для создания нового потока:

public SThread(string name, int[] mas)

{ array = mas;//Объекты одного типа (массивы это объекты)можно присваивать друг другу.

Thrd = new Thread(new ThreadStart(this.run));Thrd.Name = name;

Thrd.Start();//Запускаем поток на выполнение

}

// Начало выполнения нового потока:

void run() { Console.WriteLine(Thrd.Name + " стартовал."); rezult = Ob_sum.sumIt(array);

Console.WriteLine("Сумма для потока " + Thrd.Name + "=" + rezult);

Console.WriteLine("Поток " + Thrd.Name + " завершен!"); } }

/////////////////////////////////////////////////////////////

class Sync{static void Main(string[] args) { int[] mas ={ 1, 2, 3, 4, 5 };

SThread MyT1 = new SThread("Потомок №1", mas);

SThread MyT2 = new SThread("Потомок №2", mas);

//Метод Join сообщает системе, что приложение должно ожидать завершения потока.

MyT1.Thrd.Join(); MyT2.Thrd.Join();}}