我是線程[1]操作詳解

一、線程的定義

線程是計算機中最小的可執行單元,是操作系統中進行CPU調度和分配的基本單位,一個進程可以包含多個線程。不同於進程間的資源隔離,不同線程之間可以共享進程的資源,如內存、文件描述符等。線程主要包括線程標識符、程序計數器、寄存器集合、棧和線程本地存儲區域等組成部分。

二、線程的創建和銷毀

在C++11標準中,線程的創建和銷毀主要由std::thread類來實現,創建線程的基本形式如下:

#include <thread>
void function_to_execute();
std::thread t(function_to_execute); //創建一個新線程

創建新線程時需要指定線程需要執行的函數名或lambda表達式,在這裡function_to_execute()為線程函數,std::thread t是線程對象。銷毀線程主要有detach()函數和join()函數,前者將線程與線程對象解綁,允許線程對象獨立運行,後者等待線程執行完成後才繼續執行主線程。

三、線程的同步

多個線程之間進行資源共享時,需要注意同步問題。引入同步機制可以防止多個線程同時對同一個資源進行訪問併產生衝突,通常採用互斥量和條件變數實現同步。在C++11標準中,互斥量(std::mutex)用於保護共享數據資源,條件變數(std::condition_variable)提供了一種等待通知的機制。

#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void function1() {
    std::unique_lock<std::mutex> lck(mtx);
    // 同步執行
    cv.wait(lck, []{return ready;});
    // 繼續執行
}

void function2() {
    // 準備數據
    {
        std::lock_guard<std::mutex> lck(mtx);
        // 獲得鎖
        ready = true;
    }
    cv.notify_one();
    // 通知另一個線程
}

上面代碼中,mutex被用來保護一個boolean類型的ready變數。function1()和function2()都需要使用控制ready變數的線程同步機制來確保ready已經被設置。function1()上鎖,調用wait()函數開始等待,直到另一個線程上鎖並調用notify_one()函數來解除等待並繼續執行。function2()設置ready後,調用notify_one()函數向另一個線程通知數據已準備好。

四、線程的安全性問題

在多線程編程中,可能出現數據競爭、死鎖、飢餓、優先順序反轉等問題。其中數據競爭是典型的線程不安全問題,通常通過使用原子類型、鎖等手段來解決。原子類型是一種特殊類型,可以保證對其操作的「原子性」,即線程安全。std::atomic類提供了常用的原子類型,如std::atomic_int、std::atomic_bool等。

#include <atomic>
std::atomic_int a(0);
void increase() { a++; }

上面代碼中,std::atomic_int類的對象a可以通過該類提供的++操作進行原子遞增,從而保證多個線程之間的線程安全。

五、線程的優化

優化多線程程序的性能是程序員們需要面對的挑戰之一。線程池是一個常用的優化多線程程序的手段。線程池的本質是維護一定數量的線程,用於執行需要並發處理的任務,線程池可以避免反覆創建和銷毀線程的開銷,降低了線程創建帶來的性能影響。

#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <queue>

std::queue<std::function<void()>> taskQueue;
std::mutex taskMutex;
std::condition_variable taskCV;
std::atomic_bool stop_flag(false);

void worker() {
    std::function<void()> task;
    while (true) {
        {
            std::unique_lock<std::mutex> lock(taskMutex);
            taskCV.wait(lock, []{ return !taskQueue.empty() || stop_flag.load(); });
            if (stop_flag && taskQueue.empty()) {
                return;
            } else if (!taskQueue.empty()) {
                task = taskQueue.front();
                taskQueue.pop();
            } else {
                continue;
            }
        }
        task();
    }
}

class ThreadPool {
public:
    ThreadPool(size_t numThreads) {
        for (size_t i = 0; i < numThreads; i++) {
            workers.emplace_back(worker);
        }
    }

    ~ThreadPool() {
        stop_flag = true;
        taskCV.notify_all();
        for (auto& worker : workers) {
            worker.join();
        }
    }

    template <typename F, typename ...Args>
    auto addTask(F&& f, Args&& ...args) {
        auto task = std::make_shared<std::function<void()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        std::unique_lock<std::mutex> lock(taskMutex);
        taskQueue.emplace([task](){ (*task)(); });
        taskCV.notify_one();
        return task;
    }

private:
    std::vector<std::thread> workers;
};

ThreadPool pool(4);

void thread_func(int x, int y) {
    for (int i = x; i < y; i++) {
        printf("thread id: %d\n", std::this_thread::get_id());
        printf("i = %d\n", i);
    }
}

void test_thread_pool() {
    for (int i = 0; i < 10; i++) {
        auto task = pool.addTask(thread_func, i * 10, i * 10 + 10);
    }
}

上述代碼實現了一個簡單的線程池,包括添加任務、等待任務、執行任務等基本功能。代碼通過std::thread和std::mutex等C++標準庫提供的線程相關的類和函數實現。

原創文章,作者:HWOCS,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/370022.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
HWOCS的頭像HWOCS
上一篇 2025-04-18 13:40
下一篇 2025-04-18 13:40

相關推薦

  • Python棧操作用法介紹

    如果你是一位Python開發工程師,那麼你必須掌握Python中的棧操作。在Python中,棧是一個容器,提供後進先出(LIFO)的原則。這篇文章將通過多個方面詳細地闡述Pytho…

    編程 2025-04-29
  • Python操作數組

    本文將從多個方面詳細介紹如何使用Python操作5個數組成的列表。 一、數組的定義 數組是一種用於存儲相同類型數據的數據結構。Python中的數組是通過列表來實現的,列表中可以存放…

    編程 2025-04-29
  • Python操作MySQL

    本文將從以下幾個方面對Python操作MySQL進行詳細闡述: 一、連接MySQL資料庫 在使用Python操作MySQL之前,我們需要先連接MySQL資料庫。在Python中,我…

    編程 2025-04-29
  • Python磁碟操作全方位解析

    本篇文章將從多個方面對Python磁碟操作進行詳細闡述,包括文件讀寫、文件夾創建、刪除、文件搜索與遍歷、文件重命名、移動、複製、文件許可權修改等常用操作。 一、文件讀寫操作 文件讀寫…

    編程 2025-04-29
  • Python代碼實現迴文數最少操作次數

    本文將介紹如何使用Python解決一道經典的迴文數問題:給定一個數n,按照一定規則對它進行若干次操作,使得n成為迴文數,求最少的操作次數。 一、問題分析 首先,我們需要了解迴文數的…

    編程 2025-04-29
  • Python線程等待指南

    本文將從多個方面詳細講解Python線程等待的相關知識。 一、等待線程結束 在多線程編程中,經常需要等待線程執行完畢再進行下一步操作。可以使用join()方法實現等待線程執行完畢再…

    編程 2025-04-29
  • Python元祖操作用法介紹

    本文將從多個方面對Python元祖的操作進行詳細闡述。包括:元祖定義及初始化、元祖遍歷、元祖切片、元祖合併及比較、元祖解包等內容。 一、元祖定義及初始化 元祖在Python中屬於序…

    編程 2025-04-29
  • 如何用Python對數據進行離散化操作

    數據離散化是指將連續的數據轉化為離散的數據,一般是用於數據挖掘和數據分析中,可以幫助我們更好的理解數據,從而更好地進行決策和分析。Python作為一種高效的編程語言,在數據處理和分…

    編程 2025-04-29
  • Python列表的讀寫操作

    本文將針對Python列表的讀取與寫入操作進行詳細的闡述,包括列表的基本操作、列表的增刪改查、列表切片、列表排序、列表反轉、列表拼接、列表複製等操作。 一、列表的基本操作 列表是P…

    編程 2025-04-29
  • Python序列的常用操作

    Python序列是程序中的重要工具,在數據分析、機器學習、圖像處理等很多領域都有廣泛的應用。Python序列分為三種:列表(list)、元組(tuple)和字元串(string)。…

    編程 2025-04-28

發表回復

登錄後才能評論