Технологии Java

Введение в многопоточное программирование

Параллельное исполнение

Содержание

История

Содержание

Однозадачные системы

  • Одна задача за раз
    • Пока задача не завершилась – все ждут
    • Память – монопольное использование
    • Ввод-вывод – монопольное использование
  • Пока не завершилась – все ждут
    • Простой ресурсов
    • Большое время отклика

Пакетные

  • Набор заданий для исполнения (пакет)
    • Память – разделяемая, изолированная
    • Ввод-вывод – переключение задач
    • Управление заданиями – монитор
  • Псевдопараллельное исполнение
    • Увеличение загрузки ресурсов
    • Большое время отклика
  • 1950-е годы

Многозадачные системы

  • Несколько задач конкурируют за процессор
    • Память – разделяемая, изолированная
    • Прерывание – переключение задач
    • Ввод-вывод – разделяемый
  • Параллельное исполнение
    • Уменьшение времени отклика
  • 1960-е годы

Многопоточные программы

  • Несколько потоков конкурируют за процессор
    • Память – общая
    • Прерывание – переключение потоков
    • Ввод-вывод – разделяемый
  • Параллельное исполнение кода внутри программы
    • Уменьшение времени отклика
    • 1990-е годы

Многопоточное программирование

  • Программа одновременно имеет несколько потоков исполнения
  • Потоки могут взаимодействовать друг с другом
    • Синхронизация
    • Обмен сообщениями

Примеры

Содержание

Умножение матриц

  • // Матрицы размера n×n
    double[][] a, b, c;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            c[i][j] = 0;
            for (int k = 0; k < n; k++) {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    

Итеративный параллелизм

  • // Матрицы размера n×n
    /*shared*/ double[][] a, b, c;
    for (int i = 0; i < n; i++) {     // Параллельно
        for (int j = 0; j < n; j++) { // Параллельно
            c[i][j] = 0;
            for (int k = 0; k < n; k++) {
                c[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    

Обмен сообщениями (1)

  • Рабочий поток
    • worker[i] {
          double[]   a; // a[i][⋅]
          double[][] b; // b[⋅][⋅]
          double[]   c; // c[i][⋅]
          receive a, b from coordinator;
          for (int j = 0; j < n; j++) {
              c[j] = 0;
              for (int k = 0; k < n; k++) {
                  c[j] += a[k] * b[k][j];
              }
          }
          send c to coordinator;
      }
      

Обмен сообщениями (2)

  • Управляющий поток
    • coordinator(int i) {
          double[][] a, b, c;
          for (int i = 0; i < n; i++) {
              send a[i], b to worker[i];
          }
          for (int i = 0; i < n; i++) {
              receive c[i] from worker[i];
          }
      }
      

Обмен сообщениями (3)

  • Передача данных между рабочими потоками
    • worker[i] {
          double[] a; // a[i][⋅]
          double[] b; // b[⋅][i]
          double[] c; //  c[i][⋅]
          receive a, b from coordinator;
          for (int j = 0; j < n; j++) {
              // Вычисление c[(i - j + n) % n]
              send b to worker[(i + 1) % n];
              receive b from worker[(i + n - 1) % n];
          }
          send c to coordinator;
      }
      

Вычисление интеграла

  • Адаптивное вычисление интеграла f(x)
    double integrate(double l, double r) {
        if (abs(area(l, m) + area(m, r) - area(l, r)) > ε) {
            return integrate(l, m) + integrate(m, r);
        } else {
            return area(l, m) + area(m, r);
        }
    }
    double area(double l, double r) {
        return (f(l) + f(r)) * (r - l) / 2;
    }
    

Рекурсивный параллелизм

  • Адаптивное вычисление интеграла f(x)
    double integrate(double l, double r) {
        double m = (l + r) / 2;
        double la = area(l, m);
        double ra = area(m, r);
        if (abs(la + ra - area(l, r)) > ε) {
            la = integrate(l, m); // Параллельно
            ra = integrate(m, r); // Параллельно
        }
        return la + ra;
    }
    

Операции с потоками

Содержание

Основные операции

  • Создание потока
  • Уничтожение потока
  • Неделимая операция
    〈statements〉
    
  • Неделимая операция с ожиданием условия
    〈await(C) statements〉
    

Пример. Поиск максимума (1)

  • Без синхронизации
    /* shared */ int max = 0;
    create worker[i] {
        if (max < a[i]) max = a[i];
    }
    
  • С синхронизацией
    /* shared */ int max = 0;
    create worker[i] {
        〈if (max < a[i]) max = a[i];〉
    }
    

Пример. Поиск максимума (2)

  • Протокол проверить-проверить-установить
    /* shared */ int max = 0;
    create worker[i] {
        if (max < a[i]) {
            〈if (max < a[i]) max = a[i];〉
        }
    }
    

Свойства планировщика

  • Тип многозадачности
    • Кооперативная
    • Вытесняющая
  • Безопасность
  • Живучесть
  • Справедливость
    • Безусловная (отсутствие условий)
    • Слабая
    • Сильная

Потоки в Java

Содержание

Создание потоков

  • Класс Thread
    • Поток исполнения
    • Позволяет создавать потоки и производить операции с ними
  • Интерфейс Runnable
    • Сущность, которая может быть запущена
    • public void run()

Создание потока (Runnable)

  • Рекомендуемый способ
    // Создание
    Thread t = new Thread(() -> {
        System.out.println("Hello");
    });
    // Запуск
    t.start();
    

Создание потока (Thread)

  • Нерекомендуемый способ
    // Создание
    Thread t = new Thread() {
        public void run() {
            System.out.println("Hello");
        }
    };
    // Запуск
    t.start();
    

Состояния потока

Состояния потока

Свойства потока

  • Основные свойства
  • Свойства потока не могут изменяться после запуска

Взаимодействие потоков

Ожидание окончания потока

Прерывание потока

Дополнительные методы

Обработка данных в цикле

  • Runnable worker = run() -> {
        try {
            while (!Thread.interrupted()) {
                // Полезные действия
            }
        } catch (InterruptedException e) {
            // Поток заканчивает работу
        } finally {
            // Восстановление флага прерывания
            Thread.currentThread().interrupt();
        }
    }
    

Ссылки

Вопросы

???