C++多線程與共享指針

C++多線程與共享指針

一、C++多線程使用

2.1 thread

  • <thread> 該頭文件包含有std::thread類與std::this_thread類。以及管理線程的函數。是實現線程的主要文件。
  • <atomic> 該頭文件包含有std::atomic和std::atomic_flag類,是實現原子操作的的主要文件。
  • <mutex> 包含互斥相關的類與函數。
  • <future> 包含有future類及相關的函數。
  • <condition_variable> 包含有條件變量的類。
#include<thread>
#include<mutex>

std::thread t(func);          //無參數函數
std::thread t(func, parameter)     //帶參數函數
std::thread t(&class::func, this, parameter)     //類內函數新起線程

t.join();
t.detach();
//detach方式,啓動的線程自主在後臺運行,當前的代碼繼續往下執行,不等待新線程結束。
//join方式,等待啓動的線程完成,纔會繼續往下執行。

std::thread t3(move(t1));       //將線程從t1轉移給t3

std::this_thread::sleep_for(chrono::milliseconds(10));     //線程等待

t.get_id()//獲取線程id
auto mainThreadId = std::this_thread::get_id();      //在當前線程獲取id

//std::mutext:   獨佔的互斥量,不能遞歸使用

//std::timed_mutex:   帶超時的互斥量,不能遞歸使用。

//std::recursive_mutex:  遞歸互斥量,不帶超時功能。

//std::recursive_timed_mutex:  帶超時的遞歸互斥量

std::mutex g_lock; 
g_lock.lock();           //鎖
g_lock.unlock();        //去鎖

std::lock_guard<std::mutex> lock(mutex);       //獲取互斥量

std::recursive_mutex mutex;
std::lock_guard<std::recursive_mutex> lock(mutex);   // 獲取互斥量

2.2 pthread

#include <pthread.h>

// 定義線程的 id 變量,多個變量使用數組
std::pthread_t tids[NUM_THREADS];


std::pthread_create(thread, attr, start_routine, arg);
int ret = pthread_create(&tids[i], NULL, say_hello, NULL);
//參數依次是:創建的線程id,線程參數,調用的函數,傳入的函數參數
//thread	指向線程標識符指針。
//attr	一個不透明的屬性對象,可以被用來設置線程屬性。您可以指定線程屬性對象,也可以使用默認值 NULL。
//start_routine	線程運行函數起始地址,一旦線程被創建就會執行。
//arg	運行函數的參數。它必須通過把引用作爲指針強制轉換爲 void 類型進行傳遞。如果沒有傳遞參數,則使用 NULL。

std::pthread_exit(NULL);    //終止線程

std::pthread_join(threadid, status)     //連接線程,子程序阻礙調用程序,直到指定的 threadid 線程終止爲止。

std::pthread_detach(threadid);      //分離線程

std::pthread_attr_t attr;    //定義線程屬性
// 初始化並設置線程爲可連接的(joinable)
std::pthread_attr_init(&attr);    
std::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

// 刪除屬性
std::pthread_attr_destroy(&attr);

二、共享指針

  • 智能指針是存儲指向動態分配對象指針的類。三種智能指針:
    std::shared_ptr/std::unique_ptr/std::weak_ptr.
  • 使用時需#include<memory>

2.1 初始化

std::shared_ptr<int> p(new int(1));
std::shared_ptr<int> p2 = p;    //p和p2共享同一段內存

std::shared_ptr<int> ptr;
ptr.reset(new int(1));

int *p1 = new int[2];
std::shared_ptr<int> p3(p1); //p1和p3共享同一段內存

//使用make_shared
auto p1 = std::make_shared<int>(10);
auto p2 = std::make_shared<string>(10,"s");

2.2 獲取原始指針

std::shared_ptr<int> ptr(new int(1));
int *p = ptr.get();

2.3指定刪除器

void deleteIntPtr(int* p)
    {
        delete p;
    }
std::shared_ptr<int> p5(new int,deleteIntPtr);

//使用lambda表達式
std::shared_ptr<int> p6(new int,[](int* p){delete p;});
std::shared_ptr<int> p6(new int[10],[](int* p){delete[] p;});    //數組
std::shared_ptr<int> p7(new int[10],std::default_delete<int[]>);   //使用default_delete作爲刪除器

//封裝,使得共享指針支持共享數組
template<typename T>
std::shared_ptr<T> make_shared_array(size_t size)
{
    return std::shared_ptr<T>(new T[size],std::default_delete<T[]>());
}
std::shared_ptr<int> p8 = make_shared_array<int>(10);
std::shared_ptr<char> p9 = make_shared_array<char>(10);

2.4 注意事項

  • 不能使用原始指針初始化多個shared_ptr
int* p11 = new int;
std::shared_ptr<int> p12(p11);
std::shared_ptr<int> p13(p11);
  • 不要在實參中創建shared_ptr,應該先創建一個智能指針,再使用
deleteIntPtr(std::shared_ptr<int>(new int));//錯誤的
std::shared_ptr<int> p14(new int());
deleteIntPtr(p14);//OK
  • 要通過shared_from_this()返回this指針
struct A
{
    std::shared_ptr<A> getSelf()
    {
        return std::shared_ptr<A>(this);    //錯誤,
    }
};
int main()
{
    std::shared_ptr<A> sp1(new A);
    std::shared_ptr<A> sp2 = sp1->getSelf();//會導致重複析構
   return 0;
}


// 正確使用方式
class A:public std::enable_shared_from_this
{
public:
    std::shared_ptr<A> getSelf()
    {
        return shared_from_this();
    }
};
  • 免循環使用,如下A/B兩個指針都不會被刪除會有內存泄漏
struct A;
struct B;
struct A
{
    std::shared_ptr<B> bptr;
    ~A(){cout << "A is deleted!"<<endl;}
};
struct B
{
    std::shared_ptr<A> aptr;
    ~B() {cout << "B is deleted!"<<endl;}
};
int main()
{
    {
        std::shared_ptr<A> ap(new A);
        std::shared_ptr<B> bp(new B);
        ap->bptr = bp;
        bp->aptr = ap;
     
     }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章