Совместное использование данных, созданных одним потоком, с массивом других потоков - PullRequest
2 голосов
/ 14 января 2011

Наличие потока, который время от времени (поток с одной функцией в бесконечном цикле, данные генерируются после завершения функции) генерировал некоторые данные (например, random int). И создание трех других потоков, которым нужно время от времени получать сгенерированные данные (потоки с одной функцией в бесконечном цикле, данные требуются при запуске функции). Все эти 3 потока хотят изменить этот int во время этого круга и вернуть что-то другое.

Как сделать данные, созданные первым потоком, доступными для других потоков? (извините - я C ++ nob. Я могу использовать библиотеку boost. Прошу вас предоставить код с вашими ответами.)

Ответы [ 2 ]

3 голосов
/ 14 января 2011

Вот примитивный пример, который демонстрирует, как создать поток, который генерирует случайные числа и помещает их в очередь, и три потока потребителя, которые извлекают случайные числа из очереди и печатают их, если случайные числа являются только нечетными.Этот пример может быть значительно улучшен, и многие лучшие практики не используются для объяснения основных возможностей (thread_group, mutex и генерация случайных чисел, все с использованием boost):

#include <iostream>
#include <queue>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/random.hpp>
#include <boost/bind.hpp>

std::queue<int> random_stream;
boost::mutex random_stream_mutex, output_mutex;
// create a random number generator similar to good ol' std::rand!
boost::mt19937 rand_generator;
boost::uniform_int<> distribution;
auto random_producer = boost::bind(distribution, rand_generator);

bool isodd(int number)
{ return number % 2 == 1; }

void random_generator()
{
    for(;;)
    {
        // generate a random number, then lock the queue and push
        // the number into it.
        int random_number = random_producer();
        random_stream_mutex.lock();
        random_stream.push(random_number);
        random_stream_mutex.unlock();    
    }
}

void output_odd_randoms()
{
    for(;;)
    {
        // lock the queue then extract the number.
        random_stream_mutex.lock();
        int random_number = random_stream.front();
        random_stream.pop();
        random_stream_mutex.unlock();
        // print the extracted number if it is odd!
        if(isodd(random_number))
        {
            output_mutex.lock();
            std::cout << boost::this_thread::get_id() << ": " 
                << random_number << std::endl;
            output_mutex.unlock();
        }
    }
}

int main()
{
    // create the producer and the consumers!
    boost::thread_group threads;
    threads.create_thread(random_generator);
    threads.create_thread(output_odd_randoms);
    threads.create_thread(output_odd_randoms);
    threads.create_thread(output_odd_randoms);
    // wait for ever! :)
    threads.join_all();
}

Как видите,В коде используются глобальные переменные, но лучше инкапсулировать ваши данные.Кроме того, использование механизма блокировки RAII более элегантно, но изменение кода для их добавления тривиально.

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

3 голосов
/ 14 января 2011

Есть много способов сделать это, в зависимости от деталей.Поскольку вы не предоставляете много подробностей, давайте рассмотрим что-то простое и пуленепробиваемое.

  • Создание класса
  • Добавление личного элемента данных для хранения данных
  • Добавить потокобезопасный методы get и put для чтения и записи данных
  • Создание класса в глобальном пространстве имен
  • Кодирование потоков для использования методов get и put по мере необходимости

Как сделать потокобезопасными методы get и put?

  • Добавить частный мьютекс в ваш класс.
  • Блокировать мьютекс при входе в getи методы put
  • Разблокируйте мьютекс при выходе из методов get и put.

Примерно так:

class mySafeData
{
public:
    void Set( int i ) 
    {
        myMutex.lock();
        myData = i;
        myMutex.unlock();
    }
    void Get( int& i)
    {
        myMutex.lock();
        i = myData;
        myMutex.unlock();
    }
private:
    int myData;
    boost::mutex myMutex;

};

Этот метод неэффективен.ИМХО, важно, чтобы код работал, используя самую простую и понятную технику.Если он работает, то, если производительность является проблемой, код можно оптимизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...