天天看點

每日分享- cfree5.0 如何使用c++的線程thread

C++11 引入了線程庫,其中包括 std::thread 類,可以用來建立和管理線程。以下是使用 std::thread 的示例和潛在問題以及解決方法。

示例代碼:

#include <iostream>
#include <thread>

void myThreadFunction(int arg) {
  std::cout << "Thread started with argument: " << arg << std::endl;
  // Do some work in the thread
  std::cout << "Thread finished" << std::endl;
}

int main() {
  // Create a thread and start it
  std::thread t(myThreadFunction, 42);

  // Wait for the thread to finish
  t.join();

  return 0;
}
           

在上面的示例中,我們定義了一個 myThreadFunction 函數,該函數會被傳遞給 std::thread 構造函數,以建立一個新線程。myThreadFunction 函數在新線程中運作,并輸出一些消息。在 main 函數中,我們建立一個新線程并等待它完成。

下面着重分析一些可能出現的潛在問題:

1 線程安全問題:當多個線程同時通路共享資料時,可能會導緻競态條件和死鎖等線程安全問題。解決方法包括使用鎖和同步原語等技術,以確定對共享資源的通路是同步的。

示例代碼:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex myMutex;

void myThreadFunction(int arg) {
  // Acquire the lock before accessing shared data
  std::lock_guard<std::mutex> lock(myMutex);

  std::cout << "Thread started with argument: " << arg << std::endl;
  // Do some work in the thread
  std::cout << "Thread finished" << std::endl;
}

int main() {
  // Create a thread and start it
  std::thread t(myThreadFunction, 42);

  // Wait for the thread to finish
  t.join();

  return 0;
}
           

在上面的示例中,我們定義了一個 myMutex 互斥量,并在 myThreadFunction 函數中使用 std::lock_guard 對其進行加鎖。這確定了對共享資源的通路是同步的。

2 記憶體洩漏問題:如果線程在結束時沒有正确地清理資源,可能會導緻記憶體洩漏和其他資源洩漏問題。解決方法包括線上程結束時顯式地釋放資源,或使用 RAII 技術自動釋放資源。

示例代碼:

#include <iostream>
#include <thread>
#include <memory>

class MyThread {
public:
  MyThread(int arg) : m_arg(arg) {}
  ~MyThread() { std::cout << "MyThread destroyed" << std::endl; }

  void operator()() {
    std::cout << "Thread started with argument: " << m_arg << std::endl;
    // Do some work in the thread
    std::cout << "Thread finished" << std::endl;
  }

private:
  int m_arg;
};

int main() {
  // Create a shared_ptr to MyThread object
  std::shared_ptr<MyThread
// Create a shared_ptr to MyThread object
std::shared_ptr<MyThread> myThread = std::make_shared<MyThread>(42);

// Create a thread and start it
std::thread t(*myThread);

// Wait for the thread to finish
t.join();

// myThread is automatically destroyed, releasing its resources
return 0;
}
           

在上面的示例中,我們定義了一個 `MyThread` 類,它重載了 `operator()`,以便在新線程中運作。在 `main` 函數中,我們建立了一個 `shared_ptr`,用來管理 `MyThread` 對象的生命周期。當線程完成時,`myThread` 對象将自動被銷毀,釋放其資源。

3 異常安全問題:如果線程中的代碼抛出異常并且沒有被捕獲,可能會導緻程式崩潰或者留下未定義的行為。解決方法包括捕獲和處理異常,或使用 RAII 技術確定資源被正确清理。

示例代碼:

#include <iostream>
#include <thread>
#include <stdexcept>

void myThreadFunction(int arg) {
  std::cout << "Thread started with argument: " << arg << std::endl;
  // Do some work in the thread
  throw std::runtime_error("Oops, something went wrong!");
  std::cout << "Thread finished" << std::endl;
}

int main() {
  try {
    // Create a thread and start it
    std::thread t(myThreadFunction, 42);

    // Wait for the thread to finish
    t.join();
  }
  catch (const std::exception& e) {
    std::cerr << "Exception caught: " << e.what() << std::endl;
  }

  return 0;
}
           

在上面的示例中,我們在 myThreadFunction 函數中抛出了一個 std::runtime_error 異常。在 main 函數中,我們使用 try-catch 塊來捕獲并處理該異常,以確定程式不會崩潰。

4 線程同步問題:當多個線程通路共享資源時,可能會出現競态條件和死鎖等問題。解決方法包括使用互斥量和條件變量來保護共享資源,并避免死鎖。

示例代碼:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex myMutex;

void myThreadFunction(int arg) {
  // Lock the mutex
  myMutex.lock();
  std::cout << "Thread started with argument: " << arg << std::endl;
  // Do some work in the thread
  std::cout << "Thread finished" << std::endl;
  // Unlock the mutex
  myMutex.unlock();
}

int main() {
  // Create a thread and start it
  std::thread t1(myThreadFunction, 1);
  // Create another thread and start it
  std::thread t2(myThreadFunction, 2);

  // Wait for the threads to finish
  t1.join();
  t2.join();

  return 0;
}
           

在上面的示例中,我們使用 std::mutex 類來建立一個互斥量,并在 myThreadFunction 中使用 lock() 和 unlock() 方法來鎖定和釋放互斥量。這樣可以確定在一個線程中通路共享資源時,其他線程不能同時通路。

5 線程性能問題:建立過多的線程可能會導緻系統性能下降。解決方法包括使用線程池來重用線程,避免建立過多的線程。

示例代碼:

#include <iostream>
#include <thread>
#include <vector>

void myThreadFunction(int arg) {
  // Do some work in the thread
  std::cout << "Thread started with argument: " << arg << std::endl;
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  std::cout << "Thread finished" << std::endl;
}

int main() {
  const int numThreads = 8;
  std::vector<std::thread> threads;

  // Create a thread pool and start it
  for (int i = 0; i < numThreads; ++i) {
    threads.emplace_back(myThreadFunction, i);
  }

  // Wait for the threads to finish
  for (auto& thread : threads) {
    thread.join();
  }

  return 0;
}
           

在上面的示例中,我們使用 std::vector 來存儲線程對象,并在循環中使用 emplace_back 方法來建立線程。這樣可以友善地建立多個線程,并且不需要手動管理線程對象的生命周期。同時,我們使用 std::this_thread::sleep_for 方法來模拟線上程中進行一些耗時的操作,以便更好地觀察線程池的效果。

6 線程異常問題:線程中的異常可能會導緻程式崩潰。解決方法包括使用異常處理機制來捕獲和處理線程中的異常。

示例代碼:

#include <iostream>
#include <thread>
#include <stdexcept>

void myThreadFunction(int arg) {
  try {
    // Do some work in the thread
    std::cout << "Thread started with argument: " << arg << std::endl;
    throw std::runtime_error("Exception in thread");
    std::cout << "Thread finished" << std::endl;
  } catch (std::exception& e) {
    std::cout << "Exception caught in thread: " << e.what() << std::endl;
  }
}

int main() {
  // Create a thread and start it
  std::thread t1(myThreadFunction, 1);

  // Wait for the thread to finish
  t1.join();

  return 0;
}
           

7 線程取消問題:線程可能需要在執行過程中被取消,例如在逾時或其他條件滿足時。解決方法包括使用條件變量來等待取消請求,并在合适的時機退出線程。

示例代碼:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

std::mutex myMutex;
std::condition_variable myCondition;
bool myCancelled = false;

void myThreadFunction(int arg) {
  // Lock the mutex
  std::unique_lock<std::mutex> lock(myMutex);

  // Wait for the cancel request
  myCondition.wait(lock, []{ return myCancelled; });

  // Do some work in the thread
  std::cout << "Thread started with argument: " << arg << std::endl;
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  std::cout << "Thread finished" << std::endl;
}

int main() {
  // Create a thread and start it
  std::thread t1(myThreadFunction, 1);

  // Wait for some time
  std::this_thread::sleep_for(std::chrono::milliseconds(50));

  // Send the cancel request
  {
    std::unique_lock<std::mutex> lock(myMutex);
    myCancelled = true;
    myCondition.notify_all();
  }

  // Wait for the thread to finish
  t1.join();

  return 0;
}
           

在上面的示例中,我們使用 std::condition_variable 類來等待取消請求。我們首先在 myThreadFunction 中調用 wait 方法來等待條件變量,直到取消請求為真。在主線程中,我們使用 notify_all 方法來通知線程,使得線程從 wait 方法中傳回,并在合适的時機退出線程。

以上是一些可能出現的問題及其解決方法,需要根據具體的應用場景進行選擇和實作。

繼續閱讀