1. Главная
  2. Библиотека
  3. Программирование
  4. 1. С помощью блокирующих переменных организовать работу параллельных вычислительных потоков. Первый поток записывает в фай...
  • 👋 Решение задач

  • 📚 Программирование

решение задачи на тему:

1. С помощью блокирующих переменных организовать работу параллельных вычислительных потоков. Первый поток записывает в файл числа (до 100), не делящиеся на 2.

Дата добавления: 10.11.2024

Условие задачи

1.    С помощью блокирующих переменных организовать работу параллельных вычислительных потоков. Первый поток записывает в файл числа (до 100), не делящиеся на 2. Второй поток считывает из файла числа, проверяет, являются ли они простыми, если нет – удаляет их из файла.

2.    Постановка задачи: разработать программу для синхронизации процессов с использованием мьютексов или семафоров.

Программа должна быть реализована на языке высокого уровня. Право выбора языка предоставляется студенту. Для реализации взаимодействующих процессов использовать класс TThread. Реализовать корректную передачу данных. Протестировать программу при различных взаимных скоростях работы процессов. Для организации различных скоростей работы использовать временные задержки.

В интерфейс программы нужно включить следующие визуальные компоненты:

1.    наглядное отображение текущего содержимого буфера;

2.    для каждого потока:

- компонент для регулирования скорости работы (любой по выбору  студента);

- кнопки «Запуск», «Останов» и «Пауза». 

Исходный код программы

using System;

using System.Collections.Generic;

using System.IO;

using System.Threading;

using System.Windows.Forms;

namespace TwoThreadsApp

{

      public partial class Form1 : Form

      {

      private Object thisLock = new Object(); // объект для захватывания потоками

      string filename = "prime.txt"; // имя файла чтения/записи

      Thread reader = null; // поток чтения

      Thread writer = null; // поток записи

      bool stopWrite = false;

      bool pauseWriter = false;

      bool pauseReader = false;

      public Form1()

      {

            // Создать новый файл

            FileStream fileStream = File.Open(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);

            fileStream.Close();

            InitializeComponent();

            // установить состояние кнопок

            SetStateButtonsWriter(true, false, false);

            SetStateButtonsReader(true, false, false);

      }

      // Каждой кнопки устанавливается состояние активна/неактивана

      public void SetStateButtonsWriter(bool isStart, bool isPause, bool isStop)

      {

            btnStartThreadWrite.Enabled = isStart;

            btnPauseThreadWrite.Enabled = isPause;

            btnStopThreadWrite.Enabled = isStop;

      }

      // Каждой кнопки устанавливается состояние активна/неактивана

      public void SetStateButtonsReader(bool isStart, bool isPause, bool isStop)

      {

            btnStartThreadRead.Enabled = isStart;

            btnPauseThreadRead.Enabled = isPause;

            btnStopThreadRead.Enabled = isStop;

      }

      // Функция определения простое число или нет

      public static bool IsPrime(int number)

      {

            if (number <= 1) return false;

            if (number == 2) return true;

            if (number % 2 == 0) return false; // если делится нацело на два то возвращаем нет

            var boundary = (int)Math.Floor(Math.Sqrt(number)); // верхний лимит цикла

            // проверяем исходное число на простоту делением на число от 3 с шагом 2

            for (int i = 3; i <= boundary; i += 2)

                  if (number % i == 0)

                  return false;

            return true;

      }

      // обработчик нажатия на клавиши Запуск чтения

      private void btnStartThreadRead_Click(object sender, EventArgs e)

      {

            // если поток чтения запущен

            if (reader != null)

            {

                  if (pauseReader) // если пауза

                  {

                  pauseReader = false; // запустить продолжение его работы

                  SetStateButtonsReader(false, true, true); // обновляем состояния

                  return;

                  }

            }

            // создаем поток и устанавливаем функцию, которая будет им обрабатываться

            var threadParameters = new System.Threading.ThreadStart(delegate { ReadValuesFromFile(); });

            reader = new Thread(threadParameters);

            reader.Start(); // и запускаем его

            SetStateButtonsReader(false, true, true); // обновляем состояния

      }

      // Функция чтения значений

      public void ReadValuesFromFile()

      {

            while (!stopWrite) // пока не Стоп записи

            {

                  if (pauseReader) // ждем

                  continue;

                  lock (thisLock)// захватываем переменную

                  {

                  string tempFile = Path.GetTempFileName(); // создаем временный файл

                  using (var sw = new StreamWriter(tempFile))

                  using (var sr = new StreamReader(filename)) // поток чтения

                  {

                        string line;

                        while ((line = sr.ReadLine()) != null) // читаем строки файла

                        {

                              string[] values = (line.Split(' ')); // разбиваем строку на числа

                              string res = string.Empty;

                              foreach (var value in values) // проходим по каждому числу

                              {

                              int intVal;

                              if (Int32.TryParse(value, out intVal) && IsPrime(intVal)) // если оно простое

                              {

                                   // пишем в файл

                                   sw.Write(intVal);

                                   sw.Write(' ');

                                   res += intVal.ToString() + ' '; // и пишем в переменную

                              }

                              Action safeRead = delegate { SendToBufferRead(res); };

                              this.BeginInvoke(safeRead); // вызов функции главного потока для занесения строки в буфер

                              }

                        }

                  }

                  // переписываем временный файл в исходный

                  File.Delete(filename);

                  File.Move(tempFile, filename);

                  Thread.Sleep((int)numUpDownRead.Value);

                  }      

            }

            Action safeState = delegate { SetStateButtonsReader(true, false, false); };

            this.BeginInvoke(safeState); // вызов функции главного потока для изменения состояния кнопок

      }

      // Функция записи значений в файл

      public void WriteValuesIntoFile()

      {

            // от 1 до 100

            for (int i = 1; i < 101; ++i)

            {

                  if (pauseWriter) // если пауза то снова на цикл

                  {

                  --i;

                  continue;

                  }

                  lock (thisLock) // захватываем переменную

                  {

                  // поток записи

                  using (StreamWriter sw = File.AppendText(filename))

                  {

                        if (i % 2 != 0) // если не делится на два то пишем в файл

                        {

                              sw.Write(i);

                              sw.Write(' ');

                              Action safeWrite = delegate { SendToBufferWrite(i); };

                              this.BeginInvoke(safeWrite); // пишем результат в буфер

                        }

                  }

                  }

                  Thread.Sleep((int)numUpDownWriter.Value); // задержка потока

            }

            stopWrite = true;

            Action safeState = delegate { SetStateButtonsWriter(true, false, false); };

            this.BeginInvoke(safeState); // вызов функции главного потока для изменения состояния кнопок

      }

      // Функция записи буфер потоком чтения

      public void SendToBufferRead(string line)

      {

            textBufferRead.Clear(); // очистить буфер

            textBufferRead.AppendText(line); // добавить текст

      }

      // Функция записи буфер потоком записи

      public void SendToBufferWrite(int value)

      {

            textBufferWrite.AppendText(value + " ");

      }

      // обработчик нажатия на клавиши Запуск записи

      private void btnStartThreadWrite_Click(object sender, EventArgs e)

      {

            if (writer != null) // если поток записи созда

            {

                  if (pauseWriter) // если пауза

                  {

                  pauseWriter = false; // снимаем с паузы

                  SetStateButtonsWriter(false, true, true);

                  return;

                  }

            }

            // создаем поток записи и устанавливаем ему функцию для входа

            var threadParameters = new System.Threading.ThreadStart(delegate { WriteValuesIntoFile(); });

            writer = new Thread(threadParameters);

            writer.Start(); // запускаем

            stopWrite = false;

            SetStateButtonsWriter(false, true, true);// обновляем состояния

      }

      // обработчик нажатия на клавиши Останов записи

      private void btnStopThreadWrite_Click(object sender, EventArgs e)

      {

            writer.Abort(); // прерываем поток

            writer = null; // сделать его null

            SetStateButtonsWriter(true, false, false); // обновляем состояния

      }

      // обработчик нажатия на клавиши Пауза потока записи

      private void btnPauseThreadWrite_Click(object sender, EventArgs e)

      {

            pauseWriter = true;// флаг паузы

            SetStateButtonsWriter(true, false, false); // обновляем состояния

      }

      // обработчик нажатия на клавиши Останов потока чтения

      private void btnStopThreadRead_Click(object sender, EventArgs e)

      {

            reader.Abort(); // прерываем поток

            reader = null;

            SetStateButtonsReader(true, false, false); // обновляем состояния

      }

      // обработчик нажатия на клавиши Пауза потока чтения

      private void btnPauseThreadRead_Click(object sender, EventArgs e)

      {

            pauseReader = true;

            SetStateButtonsReader(true, false, false); // обновляем состояния

      }

      private void Form1_Load(object sender, EventArgs e)

      {

      }

      }

}

Ответ

Семафор - объект, используемый для контроля доступа нескольких потоков до общего ресурса. В общем случае можно провести аналогию семафора и переменной, состояние которой меняется каждым из потоков. Текущее состояние переменной определяет доступ к ресурсам. Над каждым семафором, можно выполнить ряд операций: увеличить значение, уменьшить или дождаться обнуления. Семафоры, как правило, применяются при синхронизации нескольких процессов и предоставляют гибкое управление ресурсами. Семафор является объектом сигнализации.

Мьютекс - объект синхронизации процессов, цель которого - блокировка критическ...

Потяни

Сводка по ответу

  • Загружено студентом
  • Проверено экспертом
  • Использовано для обучения AI
  • Доступно по подписке Кампус+

Купи подписку Кампус+ и изучай ответы

Кампус Библиотека

  • Материалы со всех ВУЗов страны

  • 1 000 000+ полезных материалов

  • Это примеры на которых можно разобраться

  • Учись на отлично с библиотекой