컴퓨터 기술이 발전하고 하드웨어 성능이 향상되면서 멀티스레딩 기술은 현대 프로그래밍에 필수적인 기술이 되었습니다. C++는 많은 강력한 멀티스레딩 기술을 제공하는 고전적인 프로그래밍 언어입니다. 이 기사에서는 독자가 멀티스레딩 기술을 더 잘 적용할 수 있도록 C++의 몇 가지 멀티스레딩 최적화 기술을 소개합니다.
1. std::thread 사용
C++11에서는 멀티스레딩 기술을 표준 라이브러리에 직접 통합하는 std::thread를 도입했습니다. std::thread를 사용하여 새 스레드를 생성하는 것은 매우 간단합니다. 함수 포인터를 전달하기만 하면 됩니다. 예:
#include <thread> #include <iostream> void hello() { std::cout << "Hello World!"; } int main() { std::thread t(hello); t.join(); return 0; }
위 코드는 새 스레드 t를 생성하고 hello 함수를 실행하며 스레드 t가 완료될 때까지 기다립니다. 스레드 생성 및 소멸에는 일정량의 오버헤드가 필요하므로 std::thread를 합리적으로 사용해야 합니다.
2. std::async 사용
std::async는 함수를 비동기적으로 실행하고 std::future 객체를 반환할 수 있는 또 다른 편리한 멀티스레딩 기술입니다. 비동기 작업 실행을 보다 편리하게 관리하고 결과를 얻으려면 std::async를 사용하세요. 예:
#include <future> #include <iostream> int add(int a, int b) { return a + b; } int main() { auto async_result = std::async(add, 1, 2); std::cout << async_result.get(); return 0; }
위 코드는 add 함수를 호출하여 1+2를 비동기적으로 계산하고 std::future 객체를 사용하여 계산 결과 획득을 관리합니다. std::async는 기본적으로 std::launch::async 전략을 사용하고 새 스레드에서 함수를 실행한다는 점에 유의해야 합니다. std::launch::deferred 전략을 사용하려면 수동으로 지정해야 합니다. 그러나 std::launch::deferred 전략을 사용하면 std::future::get()이 호출될 때만 함수가 실행되므로 사례별로 선택해야 합니다.
3. std::condition_variable을 사용하세요
멀티 스레드 프로그래밍에서는 스레드 간에 통신 및 동기화가 수행되어야 하며, std::condition_variable은 이러한 목적을 매우 잘 달성할 수 있습니다. std::condition_variable을 사용하면 한 스레드가 다른 스레드의 특정 조건이 true가 될 때까지 기다릴 수 있으므로 스레드 간 동기화가 달성됩니다. 예:
#include <condition_variable> #include <mutex> #include <thread> #include <iostream> std::mutex mutex; std::condition_variable cv; bool ready = false; void producer() { std::unique_lock<std::mutex> lock(mutex); // wait for the condition to become true cv.wait(lock, [] { return ready; }); std::cout << "Producer done." << std::endl; } void consumer() { std::this_thread::sleep_for(std::chrono::seconds(1)); ready = true; std::cout << "Consumer done." << std::endl; cv.notify_one(); } int main() { std::thread t1(producer); std::thread t2(consumer); t1.join(); t2.join(); return 0; }
위 코드는 두 개의 스레드 t1과 t2를 생성합니다. 여기서 t1은 조건 변수가 true가 될 때까지 기다리고, t2는 1초 동안 기다린 후 조건 변수를 true로 설정하고 t1에 알립니다. 여러 스레드가 동시에 조건 변수에 액세스하는 것을 방지하려면 std::condition_variable을 std::mutex와 함께 사용해야 합니다.
4. 스레드 풀 사용
생성하고 실행해야 하는 단기 작업이 많은 경우 프로그램 성능을 향상시키기 위해 스레드 풀을 사용하는 경우가 많습니다. 스레드 풀은 일정 수의 스레드를 유지하고 작업 할당 및 실행을 관리합니다. 스레드 풀을 사용하면 스레드를 자주 생성하고 삭제하는 추가 오버헤드를 방지하는 동시에 멀티 코어 CPU를 최대한 활용할 수 있습니다. 예:
#include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <vector> #include <queue> #include <functional> class ThreadPool { public: ThreadPool(std::size_t numThreads = std::thread::hardware_concurrency()) { for (std::size_t i = 0; i < numThreads; ++i) { pool.emplace_back([this] { while (!stop) { std::function<void()> task; { std::unique_lock<std::mutex> lock{ mutex }; condition.wait(lock, [this] { return stop || !tasks.empty(); }); if (stop && tasks.empty()) return; task = std::move(tasks.front()); tasks.pop(); } task(); } }); } } ~ThreadPool() { { std::unique_lock<std::mutex> lock{ mutex }; stop = true; } condition.notify_all(); for (auto& worker : pool) { worker.join(); } } template <typename F, typename... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> { using return_type = typename std::result_of<F(Args...)>::type; auto task = std::make_shared<std::packaged_task<return_type()>>( std::bind(std::forward<F>(f), std::forward<Args>(args)...)); std::future<return_type> future = task->get_future(); { std::unique_lock<std::mutex> lock{ mutex }; if (stop) throw std::runtime_error("enqueue on stopped ThreadPool"); tasks.emplace([task](){ (*task)(); }); } condition.notify_one(); return future; } private: std::vector<std::thread> pool; std::queue<std::function<void()>> tasks; std::mutex mutex; std::condition_variable condition; bool stop = false; }; void hello() { std::cout << "Hello World!" << std::endl; } int add(int a, int b) { return a + b; } int main() { { ThreadPool pool; auto f1 = pool.enqueue(hello); auto f2 = pool.enqueue(add, 1, 2); std::cout << f2.get() << std::endl; } return 0; }
위 코드는 여러 스레드와 작업 대기열을 포함하는 ThreadPool 클래스를 정의합니다. 스레드 풀은 작업 대기열에서 작업을 계속 가져와 대기열이 비어 있거나 스레드 풀이 중지될 때까지 실행합니다. ThreadPool::enqueue 메소드를 사용하여 작업 큐에 작업을 추가하고 std::future 객체를 반환하여 작업 실행 결과를 관리합니다.
일반적으로 C++는 개발자가 멀티 코어 CPU의 성능을 활용하고 스레드와 작업을 보다 유연하게 관리할 수 있도록 다양한 멀티 스레딩 기술을 제공합니다. 개발자는 프로그램 성능을 최적화하기 위해 이러한 기술을 적절하게 사용해야 합니다.
위 내용은 C++의 멀티스레딩 최적화 기술의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!