Временные потоки в C++

Как я могу разделить программу на C++ на 2 временных потока?

Задача выглядит так: случайный элемент добавляется в разнообразие каждые t секунд, а случайный элемент удаляется из множества каждые n секунд. N и t - произвольно выбранные числа.

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

std::thread. убедитесь, что ресурсы, совместно используемые потоками, каким-либо образом защищены от одновременного доступа. std::mutex может здесь помочь.
user4581301 16.11.2018 20:36
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
1
1 143
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Один (несинхронизированный) подход

В C++ 11 и новее вы можете использовать std::thread, std::mutex и std::atomic, чтобы делать что-то вроде

#include <atomic>
#include <mutex>
#include <thread>

void n_function(varietyType variety, int n);

std::mutex mtx;
std::atomic<int> time = 0;
int end = 0;      // This must be given a value greater than zero for anything to happen

int main() {
  int t;      // These must be assigned a value larger than zero
  int n;      // Additionally, they are type-agnostic - they don't have to be int,
              // if the rest of this example code is modified accordingly.

  std::thread n_thread(n_function, variety, n);

  int prev = time;
  while (time < end) {
    time += 1;
    if (time - prev >= t) {
      prev = time;
      mtx.lock();
      // add element
      mtx.unlock();
    }
  }
  n_thread.join();
}

где n_function - это

void n_function(varietyType variety, int n) {
  int prev = time;
  while (time < end) {
    if (time - prev >= n) {
      prev = time;
      mtx.lock();
      // delete element
      mtx.unlock();
    }
  }
}

Примечание

  • Это будет работать очень быстро (за исключением мьютекса), но поскольку потоки не блокируются, он склонен к отсутствию удалений (например, при выполнении 1000 шагов с n_h = 4 может быть выполнено только 241 удаление вместо 250, как предполагалось), особенно если элементы удаляются чаще, чем добавляются. Кроме того, будет иметь значение скорость, с которой элемент может быть добавлен или удален - более быстрое добавление / удаление увеличивает вероятность промаха.

  • Если вы хотите привязать это к часам вашего процессора и иметь секунды t и n, отражающие время действительный в секундах «настенных часов», я бы рекомендовал взглянуть на std::chrono вместо использования атомного счетчика.

  • Для более длительных интервалов времени используйте std::atomic<unsigned long> time или даже std::atomic<unsigned long long> time по мере необходимости.

Другой (синхронный) подход

Если скорость менее важна, чем точность (а в действительности для большинства случаев использования эти два подхода будут очень близки по скорости), то, возможно, лучше использовать три потока (два дочерних, один родительский) для изменения разнообразия. т.е.

#include <atomic>
#include <mutex>
#include <thread>

std::mutex mtx;

void n_function(varietyType variety, int n);
void t_function(varietyType variety, int t);

std::atomic<int> check = 0;
std::atomic<int> time = 0;
int end = 0;      // This must be given a value greater than zero for anything to happen

int main() {
  int t;        // Again these must be given a value greater than 0
  int n;
  std::thread n_thread(n_function, variety, n);
  std::thread t_thread(t_function, variety, t);

  while (time < end) {
    time += 1;
    check = 2;
    while (check != 0) {}    // blocking wait loop - use caution
  }
  n_thread.join();
  t_thread.join();
}

Где t_function и n_function

void t_function(varietyType variety, int t) {
    int prev = time;
    while (time < end) {
        if (time - prev >= t && check > 0) {
          prev = time;
          mtx.lock();
          // add element
          mtx.unlock();
        }
        check --;
    }
}

void n_function(varietyType variety, int n) {
    int prev = time;
    while (time < end) {
        if (time - prev >= n && check > 0) {
          prev = time;
          mtx.lock();
          // add element
          mtx.unlock();
        }
        check --;
    }
}

Примечание

  • Оба подхода предполагают, что variety является разделяемой памятью, объявленной либо как указатель, либо явно объявленной как разделяемая память.

  • Оба этих метода могут (и, вероятно, будут) быть более неэффективными, чем однопоточный подход, если только добавление / удаление элемента не требует больших вычислительных затрат (т.е. если есть значительные вычисления, связанные с решением об удалении, или если элемент имеет большой объем памяти. след).

  • Лично синхронные подходы, подобные этому, когда потоки должны ждать друг друга, заставляют меня нервничать, потому что, если какой-либо из них зависает по какой-либо причине, все это зависает - в зависимости от приложения, которое может быть хуже, чем зависание только одного или нескольких потоков.

Надеюсь это поможет.

Очень полезный ответ

user10737101 10.12.2018 02:27

Другие вопросы по теме