精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

快手C++一面初試:手寫單例模式代碼

開發 前端
實際運行時,多線程部分的輸出順序可能因系統調度而有所不同,但始終會保證打印隊列計數的正確性和實例的唯一性。每次打印會有 2 秒的延遲(模擬實際打印耗時)。

作為 C++ 開發者,你一定遇到過這樣的場景:日志系統需要全局唯一的實例記錄操作,配置管理器不能重復加載配置文件,數據庫連接池更容不得多實例搶占資源。這些場景的核心訴求驚人地一致 ——確保某個類在程序生命周期中只有一個實例。這正是單例模式大顯身手的地方。它像程序世界里的 "獨生子女證",嚴格管控類的實例數量,同時提供全局訪問點。看似簡單的設計,卻藏著不少坑:多線程環境下的競態條件、內存泄漏風險、拷貝構造函數的防濫用。

今天我們直擊核心,手把手寫透 5 種 C++ 單例實現。從最基礎的懶漢模式到 C++11 的局部靜態變量方案,從線程安全隱患分析到性能優化技巧,每個代碼片段都附帶避坑指南。無論你是剛接觸設計模式的新手,還是想重構老舊單例的老兵,這篇實戰指南都能讓你徹底掌握單例模式的精髓。

Part1.單例模式簡介

1.1單例模式概述

單例模式,從名字上就能看出它的獨特之處 ——“單例”,即單個實例。在 C++ 中,它是一種設計模式,確保一個類僅有一個實例存在于整個程序的生命周期中 ,并且為這個唯一的實例提供一個全局的訪問點。就像在一個大型的軟件系統中,有一個專門負責管理系統配置的類,這個類只需要創建一個實例就可以為整個系統提供服務,如果創建多個實例,不僅會浪費系統資源,還可能導致配置信息的不一致。通過單例模式,我們可以保證這個配置類在程序中只有一個實例,所有需要獲取或修改系統配置的地方都可以通過這個單例實例來進行操作。

1.2生活中的類比

為了更好地理解單例模式,我們可以將它類比到生活中的場景。想象一下,你所在的公司有一位總經理,這位總經理在公司中是獨一無二的存在,他掌握著公司的重要決策權,負責公司的整體運營和發展方向。公司的各個部門,無論是銷售部門、研發部門還是財務部門,在遇到重要決策或需要協調資源時,都會去找總經理。

總經理就像是單例模式中的唯一實例,而各個部門就像是程序中的不同模塊,它們都通過這個唯一的 “總經理” 來獲取決策和資源協調,這就是單例模式在生活中的生動體現。再比如學校里的校長,全校只有一位校長,他管理著學校的各項事務,師生們如果有重要的事情需要學校層面的決策,都會去找校長。校長這個角色就如同單例模式中的類的唯一實例,為整個學校這個 “系統” 提供了統一的管理和決策的入口。

1.3為什么使用單例模式

單例模式在編程中有著廣泛的應用和重要的作用。首先,它可以節省內存資源。因為一個類只有一個實例,不會像普通類那樣被多次實例化,從而減少了內存的占用。在一個大型的游戲開發項目中,游戲的配置信息,如畫面分辨率、音效音量等,這些配置在整個游戲運行過程中只需要一份實例就可以了,如果每個模塊都去創建自己的配置實例,不僅會浪費大量的內存資源,還可能導致不同模塊獲取到的配置不一致,從而引發各種奇怪的問題。這時候單例模式就派上用場啦,通過將配置信息封裝在一個單例類中,整個游戲程序都可以通過這個單例類來獲取和修改配置,既保證了配置的一致性,又節省了內存資源。

其次,單例模式方便管理全局資源。在一個企業級應用中,數據庫連接是一種非常寶貴的資源,創建和銷毀數據庫連接都需要消耗一定的時間和系統資源。如果每個業務模塊都獨立地創建和管理自己的數據庫連接,那么在高并發的情況下,很容易導致系統資源耗盡,性能急劇下降。而使用單例模式來管理數據庫連接,就可以確保整個應用程序中只有一個數據庫連接實例,所有的業務模塊都共享這個連接,大大提高了資源的利用率和系統的性能。

此外,單例模式還可以避免資源的重復占用。例如,在一個多線程的環境中,如果多個線程都嘗試創建同一個資源的實例,可能會導致資源的沖突和不一致。而通過單例模式,我們可以保證這個資源只有一個實例,所有線程都共享這個實例,從而避免了資源的重復占用和沖突。

Part2.手寫C++ 單例模式代碼實現

2.1基本要點剖析

在實現 C++ 單例模式時,有幾個關鍵的要點需要把握。首先,要將構造函數私有化。這是為了防止外部代碼通過new操作符隨意創建類的實例,從而確保整個程序中只有一個實例存在。就好比一個珍貴的限量版藝術品,只有特定的授權人員才能接觸和操作,其他人無法私自復制或創建。例如:

class Singleton {
private:
    Singleton() {}  // 私有化構造函數
};

其次,需要一個私有靜態實例指針來保存唯一的實例。這個指針就像是一個特殊的 “管家”,專門負責管理和指向這個唯一的實例。因為是靜態的,所以它在整個程序運行期間都存在,并且只有一份。示例代碼如下:

class Singleton {
private:
    static Singleton* instance;  // 私有靜態實例指針
    Singleton() {}
};
Singleton* Singleton::instance = nullptr;  // 在類外初始化指針為nullptr

最后,提供一個公共靜態方法作為訪問實例的接口。通過這個接口,其他代碼就可以獲取到這個唯一的實例,就像通過一扇專門的門進入一個房間,而這個房間里存放著唯一的 “寶藏”(單例實例)。例如:

class Singleton {
public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
private:
    static Singleton* instance;
    Singleton() {}
};
Singleton* Singleton::instance = nullptr;

2.2懶漢模式(線程不安全)

class Singleton {
public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
private:
    static Singleton* instance;
    Singleton() {}
};
Singleton* Singleton::instance = nullptr;

懶漢模式的核心原理是延遲初始化。它就像一個懶人,只有在真正被需要(第一次調用getInstance方法)的時候,才會去創建實例。在程序啟動時,并不會立即創建實例,而是等到有代碼調用getInstance方法,并且發現instance指針為空時,才會創建一個新的實例并返回。這種方式在一些情況下可以節省資源,因為如果單例實例在整個程序運行過程中都沒有被使用,那么就不會浪費資源去創建它。

然而,懶漢模式在多線程環境下存在嚴重的問題。想象一下,有多個線程同時調用getInstance方法,并且都判斷instance為空。由于線程的并發執行,這些線程可能會同時進入創建實例的代碼塊,從而導致創建多個實例,這就違背了單例模式的初衷。例如,在線程 A 判斷instance為空后,還沒來得及創建實例時,線程 B 也判斷instance為空,然后兩個線程都創建了各自的實例,這樣就破壞了單例的唯一性。

2.3懶漢模式(線程安全 - 加鎖實現)

#include <mutex>

class Singleton {
public:
    static Singleton* getInstance() {
        std::lock_guard<std::mutex> lock(mutex);
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
private:
    static Singleton* instance;
    static std::mutex mutex;
    Singleton() {}
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

為了解決懶漢模式的線程安全問題,可以使用互斥鎖。這里使用了std::lock_guard,它是一個 RAII(Resource Acquisition Is Initialization)類,在構造時自動加鎖,在析構時自動解鎖。當一個線程進入getInstance方法時,std::lock_guard會自動加鎖,這樣其他線程就無法進入這個代碼塊,直到當前線程解鎖。在加鎖后,再判斷instance是否為空,如果為空則創建實例,從而保證了在多線程環境下只有一個實例被創建。

雖然加鎖實現保證了線程安全,但也帶來了性能開銷。每次調用getInstance方法時都需要加鎖和解鎖,而加鎖和解鎖操作是有一定時間成本的。如果這個方法被頻繁調用,那么頻繁的加鎖解鎖操作會降低程序的執行效率。就像每次進入一個房間都要進行繁瑣的安檢(加鎖)和解除安檢(解鎖),會大大影響進入房間的速度。在高并發場景下,這種性能開銷可能會成為系統的瓶頸。

2.4懶漢模式(線程安全 - 雙重檢查鎖定 DCL)

#include <mutex>

class Singleton {
public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }
private:
    static Singleton* instance;
    static std::mutex mutex;
    Singleton() {}
};
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

雙重檢查鎖定(DCL)是對加鎖實現的進一步優化。它的原理是進行兩次檢查。第一次檢查instance是否為空,如果不為空,直接返回實例,這樣就避免了不必要的加鎖操作,提高了性能。只有當第一次檢查發現instance為空時,才會進入加鎖代碼塊。在加鎖后,再進行第二次檢查,這是因為可能有多個線程同時通過了第一次檢查,所以需要在加鎖后再次確認instance是否為空,確保只有一個實例被創建。這種方式既保證了線程安全,又在一定程度上減少了加鎖帶來的性能開銷。

在 C++11 之前,雙重檢查鎖定存在內存屏障問題。由于編譯器和 CPU 的優化,可能會導致指令重排序,使得一個線程在instance還未完全初始化時就返回了它,從而導致其他線程訪問到未初始化的對象。為了解決這個問題,在 C++11 之前需要使用volatile關鍵字來修飾instance指針,防止指令重排序。在 C++11 及之后,內存模型得到了改進,std::mutex已經保證了內存的可見性和順序性,所以在一般情況下不需要再顯式使用volatile關鍵字,但在一些特殊場景下,仍然需要根據具體情況進行考慮。

2.5餓漢模式

class Singleton {
public:
    static Singleton* getInstance() {
        return instance;
    }
private:
    static Singleton* instance;
    Singleton() {}
};
Singleton* Singleton::instance = new Singleton();

餓漢模式與懶漢模式相反,它在類加載時就創建實例。當程序啟動,類被加載到內存中時,instance就已經被創建好了。因為類加載過程是由系統控制的,在這個過程中不存在多線程競爭,所以天然是線程安全的。之后,任何代碼調用getInstance方法,都會直接返回已經創建好的實例。

餓漢模式的優點很明顯,實現簡單,不需要考慮復雜的線程安全問題,因為實例在類加載時就已經創建,不存在多線程并發創建的情況。而且由于不需要加鎖解鎖,性能也相對較高。然而,它也有缺點,那就是可能會造成資源浪費。如果這個單例實例在整個程序運行過程中都沒有被使用,那么在程序啟動時就創建它就會白白占用內存資源。就像提前準備好了一件可能永遠都不會用到的工具,占據了寶貴的空間。

2.6局部靜態變量實現(C++11 及以上)

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
private:
    Singleton() {}
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

在 C++11 及以上版本中,可以利用局部靜態變量的特性來實現單例模式。當getInstance方法第一次被調用時,會創建局部靜態變量instance。C++11 保證了局部靜態變量的初始化是線程安全的,即多個線程同時調用getInstance方法,只會有一個線程能夠初始化instance,其他線程會等待初始化完成。這種方式實現了延遲初始化,只有在第一次調用getInstance方法時才創建實例,同時又保證了線程安全。

這種實現方式具有很多優勢。首先,它非常簡潔,代碼量少,不需要復雜的加鎖操作或雙重檢查。其次,它自動處理了內存回收問題,當程序結束時,局部靜態變量會自動銷毀,不需要手動管理內存。此外,它還天然地防止了拷貝和移動操作,通過刪除拷貝構造函數和賦值運算符重載,確保了單例的唯一性不會被破壞。這種方式在 C++11 及以上版本中是實現單例模式的一種推薦方式,兼具簡潔性、安全性和高效性。

Part3.不同實現方式對比

3.1性能對比

從時間復雜度來看,餓漢模式在程序啟動時就創建實例,后續獲取實例的操作時間復雜度為 O (1),因為不需要任何判斷和創建操作,直接返回已創建好的實例。而懶漢模式(非線程安全和線程安全 - 加鎖實現)在第一次獲取實例時需要進行判斷和創建操作,時間復雜度為 O (1),但線程安全 - 加鎖實現每次獲取實例都需要加鎖解鎖,這部分操作雖然時間復雜度也是 O (1),但加鎖解鎖本身有一定的時間開銷。

雙重檢查鎖定(DCL)優化后的懶漢模式,在正常情況下(實例已創建),第一次檢查就可以直接返回實例,時間復雜度為 O (1),只有在第一次創建實例時才會有加鎖操作,相對減少了鎖競爭,提高了性能。局部靜態變量實現同樣在第一次調用getInstance方法時創建實例,時間復雜度為 O (1),并且由于 C++11 保證了局部靜態變量初始化的線程安全性,后續調用也無需額外的同步操作,性能表現較好。

在空間復雜度方面,所有實現方式在正常情況下都只創建一個實例,空間復雜度為 O (1)。但如果考慮到線程安全的實現方式中使用的互斥鎖等同步機制,會額外占用一些內存空間,不過這個額外空間通常較小,一般可以忽略不計 。在多線程并發環境下獲取實例時,餓漢模式由于實例已經提前創建好,不存在多線程競爭創建的問題,性能較為穩定。而懶漢模式的非線程安全版本在多線程環境下會出現創建多個實例的錯誤情況,無法保證單例的正確性,也就談不上性能了。

懶漢模式的線程安全 - 加鎖實現,每次獲取實例都加鎖,在高并發場景下,頻繁的加鎖解鎖操作會導致線程上下文切換頻繁,嚴重影響性能。雙重檢查鎖定雖然減少了鎖競爭,但在多線程并發時,仍可能存在一定的鎖沖突,不過相比每次都加鎖的方式,性能有了顯著提升。局部靜態變量實現利用 C++11 的特性,在多線程并發獲取實例時,能夠高效地保證線程安全,且沒有額外的鎖開銷,性能表現最佳。

3.2資源占用對比

懶漢模式和餓漢模式在內存占用和資源初始化時間上存在明顯差異。餓漢模式在程序啟動時就創建實例,這意味著無論這個實例在后續是否被使用,它所占用的內存資源都會一直存在,直到程序結束。如果單例實例占用的內存較大,或者初始化時需要加載大量的數據或執行復雜的初始化操作,那么在程序啟動階段就會消耗較多的內存和系統資源,可能會導致程序啟動時間變長。例如,在一個圖形渲染引擎中,如果將渲染器的配置信息管理類設計為餓漢式單例,并且這個配置類在初始化時需要讀取大量的圖形資源配置文件,那么在程序啟動時就會占用較多的內存和磁盤 I/O 資源,影響程序的啟動速度。

懶漢模式則是延遲初始化,只有在第一次調用getInstance方法時才會創建實例。這在一定程度上節省了內存資源,因為如果單例實例在整個程序運行過程中都沒有被使用,那么就不會占用內存空間。然而,這種延遲初始化也帶來了一些問題。在多線程環境下,為了保證線程安全,需要使用同步機制,如加鎖或雙重檢查鎖定,這些同步機制會增加代碼的復雜性和執行開銷。而且,第一次創建實例時可能會因為初始化操作而導致一定的性能抖動,如果這個初始化操作比較耗時,可能會影響到程序的實時性。比如在一個實時通信系統中,如果將通信連接管理類設計為懶漢式單例,并且在第一次創建實例時需要進行復雜的網絡連接初始化和認證操作,那么在第一次使用該單例時,可能會導致通信延遲,影響用戶體驗。

3.3使用場景建議

根據應用場景的線程環境和資源需求等因素,可以合理選擇不同的單例模式實現方式。如果應用場景是單線程環境,那么非線程安全的懶漢模式就可以滿足需求,因為它實現簡單,且能實現延遲初始化,節省資源。例如,在一個簡單的命令行工具中,由于不存在多線程并發的情況,使用非線程安全的懶漢模式來實現單例類,既可以保證單例的唯一性,又能減少不必要的同步開銷。

在多線程環境下,如果單例實例占用的資源較少,或者初始化開銷不大,且對線程安全要求較高,餓漢模式是一個不錯的選擇。因為它實現簡單,天生線程安全,在程序啟動時就創建實例,避免了多線程并發創建帶來的問題。比如在一個小型的多線程服務器程序中,用于管理服務器基本配置信息的單例類,由于配置信息占用資源較少,使用餓漢模式可以快速創建實例,并且保證在多線程環境下的安全訪問。

如果單例實例占用資源較大,且希望實現延遲初始化,同時保證多線程安全,雙重檢查鎖定(DCL)的懶漢模式或局部靜態變量實現是比較好的選擇。在 C++11 及以上版本中,局部靜態變量實現更為推薦,因為它代碼簡潔,利用了 C++11 的線程安全特性,性能高效。

例如,在一個大型的游戲開發項目中,用于管理游戲場景資源的單例類,由于場景資源占用內存較大,使用局部靜態變量實現的單例模式,可以在第一次使用場景資源時才進行加載和初始化,同時保證多線程環境下的安全訪問,提高游戲的性能和資源利用率。如果項目需要兼容舊版本的 C++,那么雙重檢查鎖定的懶漢模式可以在保證線程安全的前提下,盡量減少鎖帶來的性能開銷 。

Part4.案例分析實戰

4.1定義

一個類僅能存在唯一實例,且該實例需由類自身創建,并向整個系統提供一個全局的訪問方式。具體要點如下:

  • 該類不允許存在多個實例,僅有一個實例是其核心特征;
  • 實例的創建過程由類自身完成,無需外部干預;
  • 類要主動為整個系統提供獲取該實例的途徑。

4.2單例模式結構代碼

singleton.h文件代碼如下:

#include "Singleton.h"
#include <iostream>

// 初始化靜態成員變量
Singleton* Singleton::instance = nullptr;

// 構造函數實現
Singleton::Singleton()
{
    std::cout << "Singleton instance created" << std::endl;
}

// 獲取實例的實現
Singleton* Singleton::getInstance()
{
    if (instance == nullptr)
    {
        instance = new Singleton();
    }
    return instance;
}

// 示例方法實現
void Singleton::showMessage()
{
    std::cout << "Hello from Singleton!" << std::endl;
}

singleton.cpp文件代碼如下:

#ifndef SINGLETON_H
#define SINGLETON_H

class Singleton
{
public:
    // 提供全局訪問點
    static Singleton* getInstance();

    // 示例方法,用于測試
    void showMessage();

protected:
    // 保護構造函數,防止外部實例化
    Singleton();

private:
    // 唯一實例的靜態指針
    static Singleton* instance;
};

#endif // SINGLETON_H

main.cpp文件代碼如下:

#include "Singleton.h"

int main()
{
    // 獲取單例實例并使用
    Singleton* singleton = Singleton::getInstance();
    singleton->showMessage();

    // 驗證單例特性(再次獲取實例應該是同一個對象)
    Singleton* anotherSingleton = Singleton::getInstance();
    if (singleton == anotherSingleton)
    {
        std::cout << "Both instances are the same - singleton works!" << std::endl;
    }

    return 0;
}

編譯時,需要將這三個文件一起編譯(例如:g++ Singleton.cpp main.cpp -o singleton),然后運行生成的可執行文件即可。

4.3打印機實例

singleton.h文件代碼如下:

#ifndef SINGLETON_H
#define SINGLETON_H

#include <mutex>
#include <string>

// 打印機單例類
class Printer
{
public:
    // 禁止復制和賦值,確保實例唯一性
    Printer(const Printer&) = delete;
    Printer& operator=(const Printer&) = delete;

    // 獲取全局唯一打印機實例
    static Printer* getInstance();

    // 打印文檔方法
    void printDocument(const std::string& documentName);

    // 獲取打印隊列長度
    int getPrintQueueLength() const;

    // 銷毀打印機實例
    static void destroyInstance();

protected:
    // 保護的構造函數,防止外部直接創建實例
    Printer();

    // 保護的析構函數,確保正確銷毀
    ~Printer();

private:
    // 靜態指針指向唯一實例
    static Printer* instance;

    // 線程安全鎖
    static std::mutex mtx;

    // 打印隊列長度計數器
    int printQueueLength;
};

#endif // SINGLETON_H

singleton.cpp文件代碼如下:

#include "singleton.h"
#include <iostream>
#include <chrono>
#include <thread>

// 初始化靜態成員變量
Printer* Printer::instance = nullptr;
std::mutex Printer::mtx;

// 構造函數:初始化打印隊列
Printer::Printer() : printQueueLength(0)
{
    std::cout << "打印機實例已初始化" << std::endl;
}

// 析構函數:清理資源
Printer::~Printer()
{
    std::cout << "打印機實例已銷毀" << std::endl;
}

// 獲取全局唯一實例(線程安全)
Printer* Printer::getInstance()
{
    // 雙重檢查鎖定,提高多線程環境下的性能
    if (instance == nullptr)
    {
        std::lock_guard<std::mutex> lock(mtx); // 加鎖確保線程安全
        if (instance == nullptr)
        {
            instance = new Printer();
        }
    }
    return instance;
}

// 打印文檔實現
void Printer::printDocument(const std::string& documentName)
{
    std::lock_guard<std::mutex> lock(mtx); // 確保打印操作的線程安全
    printQueueLength++;
    std::cout << "\n開始打印文檔: " << documentName << std::endl;
    std::cout << "當前打印隊列長度: " << printQueueLength << std::endl;

    // 模擬打印過程
    std::this_thread::sleep_for(std::chrono::seconds(2));

    std::cout << "文檔 " << documentName << " 打印完成" << std::endl;
    printQueueLength--;
    std::cout << "當前打印隊列長度: " << printQueueLength << std::endl;
}

// 獲取打印隊列長度
int Printer::getPrintQueueLength() const
{
    return printQueueLength;
}

// 銷毀實例
void Printer::destroyInstance()
{
    std::lock_guard<std::mutex> lock(mtx);
    if (instance != nullptr)
    {
        delete instance;
        instance = nullptr;
    }
}

main.cpp文件代碼如下:

#include "singleton.h"
#include <iostream>
#include <thread>
#include <vector>
#include <string>

// 打印任務函數,用于多線程測試
void printTask(const std::string& documentName)
{
    // 獲取打印機實例
    Printer* printer = Printer::getInstance();

    // 執行打印
    printer->printDocument(documentName);
}

int main()
{
    std::cout << "=== 打印機單例模式測試 ===" << std::endl;

    // 測試1:單線程打印
    std::cout << "\n--- 單線程打印測試 ---" << std::endl;
    Printer* printer = Printer::getInstance();
    printer->printDocument("報告.pdf");
    printer->printDocument("圖片.png");

    // 測試2:多線程打印(模擬多個應用程序同時使用打印機)
    std::cout << "\n--- 多線程打印測試 ---" << std::endl;
    std::vector<std::thread> threads;

    // 創建5個打印線程
    for (int i = 1; i <= 5; ++i)
    {
        std::string docName = "文檔" + std::to_string(i) + ".txt";
        threads.emplace_back(printTask, docName);
    }

    // 等待所有線程完成
    for (auto& t : threads)
    {
        t.join();
    }

    // 測試3:驗證單例唯一性
    std::cout << "\n--- 單例唯一性驗證 ---" << std::endl;
    Printer* printer2 = Printer::getInstance();
    if (printer == printer2)
    {
        std::cout << "驗證成功:兩次獲取的是同一個打印機實例" << std::endl;
    }
    else
    {
        std::cout << "驗證失敗:獲取了不同的打印機實例" << std::endl;
    }

    // 銷毀打印機實例
    Printer::destroyInstance();

    return 0;
}

Makefile文件:

CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra -pthread
TARGET = printer_app
SRCS = main.cpp singleton.cpp
OBJS = $(SRCS:.cpp=.o)
HEADER = singleton.h

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CXX) $(CXXFLAGS) -o $@ $^
	@echo "編譯完成: $(TARGET)"

%.o: %.cpp $(HEADER)
	$(CXX) $(CXXFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)
	@echo "清理完成"

run: $(TARGET)
	./$(TARGET)

.PHONY: all clean run

運行效果如下所示:

=== 打印機單例模式測試 ===

--- 單線程打印測試 ---
打印機實例已初始化

開始打印文檔: 報告.pdf
當前打印隊列長度: 1
文檔 報告.pdf 打印完成
當前打印隊列長度: 0

開始打印文檔: 圖片.png
當前打印隊列長度: 1
文檔 圖片.png 打印完成
當前打印隊列長度: 0

--- 多線程打印測試 ---

開始打印文檔: 文檔1.txt
當前打印隊列長度: 1
文檔 文檔1.txt 打印完成
當前打印隊列長度: 0

開始打印文檔: 文檔2.txt
當前打印隊列長度: 1
文檔 文檔2.txt 打印完成
當前打印隊列長度: 0

開始打印文檔: 文檔3.txt
當前打印隊列長度: 1
文檔 文檔3.txt 打印完成
當前打印隊列長度: 0

開始打印文檔: 文檔4.txt
當前打印隊列長度: 1
文檔 文檔4.txt 打印完成
當前打印隊列長度: 0

開始打印文檔: 文檔5.txt
當前打印隊列長度: 1
文檔 文檔5.txt 打印完成
當前打印隊列長度: 0

--- 單例唯一性驗證 ---
驗證成功:兩次獲取的是同一個打印機實例
打印機實例已銷毀
  • 程序啟動后首先顯示測試標題,然后進行單線程打印測試
  • 首次獲取打印機實例時會初始化并顯示 "打印機實例已初始化"
  • 每個打印任務會顯示開始打印、當前隊列長度、打印完成等信息
  • 多線程測試中,由于加鎖機制,打印任務會按順序執行(實際多線程環境可能有不同的執行順序,但隊列計數始終準確)
  • 單例唯一性驗證通過,確認兩次獲取的是同一個實例
  • 程序結束時銷毀打印機實例,顯示 "打印機實例已銷毀"

實際運行時,多線程部分的輸出順序可能因系統調度而有所不同,但始終會保證打印隊列計數的正確性和實例的唯一性。每次打印會有 2 秒的延遲(模擬實際打印耗時)。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2025-05-27 10:15:00

void*函數開發

2015-09-06 11:07:52

C++設計模式單例模式

2010-02-05 17:00:06

C++單例模式

2025-03-24 07:35:00

開發注解Spring

2010-02-03 09:43:16

C++單例模式

2022-10-10 08:13:16

遞歸通用代碼

2021-04-29 07:18:21

Spring IOC容器單例

2025-03-13 10:01:47

2023-03-21 15:21:52

開發程序設計static

2010-01-27 10:45:21

C++單例模式

2025-08-11 05:00:00

2010-02-06 13:42:36

C++單件模式

2025-08-26 02:15:00

C++函數Student

2025-08-28 09:21:25

2022-05-24 08:09:00

HadoopHiveSpark

2025-08-18 02:12:00

2025-08-13 01:00:00

2023-11-13 16:49:51

C++單例

2022-05-11 22:15:51

云計算云平臺

2021-09-07 10:44:35

異步單例模式
點贊
收藏

51CTO技術棧公眾號

国产玉足脚交久久欧美| 亚洲www视频| 久久中文字幕精品| 欧美一级做a| 一区二区不卡在线播放| 久久精品人人做人人爽电影| 中文字幕在线日亚洲9| 一区二区免费不卡在线| 日韩av在线精品| 搡女人真爽免费午夜网站| av在线麻豆| 久久亚区不卡日本| 亚洲最大的网站| 五月天婷婷久久| 欧美激情 亚洲a∨综合| 亚洲美女在线观看| jjzz黄色片| 国产成人毛片| 大桥未久av一区二区三区| 中文字幕中文字幕一区三区| 日韩一二三四| 欧美视频13p| 久久成人免费视频| 成年人网站免费看| 二区三区精品| 在线观看亚洲专区| av在线com| 麻豆传媒在线观看| 在线播放麻豆| 美国十次了思思久久精品导航| 久久久久久国产三级电影| 九九精品视频免费| 精品国产乱码久久久久久蜜坠欲下| 欧美成人乱码一区二区三区| 国产精品一区二区小说| 亚洲同志男男gay1069网站| 亚洲最新视频在线观看| 中国一级黄色录像| www.黄在线观看| 久久亚洲精华国产精华液| 国产精品国产三级欧美二区| 国产精品老熟女视频一区二区| 天堂在线亚洲视频| 97在线视频免费| 五月天婷婷网站| 亚洲午夜极品| 欧美日本啪啪无遮挡网站| 亚洲欧美精品aaaaaa片| 日韩精品免费一区二区在线观看 | 国产一区二区亚洲| 亚洲欧美日韩国产精品| 免费无码一区二区三区| 美女主播精品视频一二三四| 亚洲成年人在线| jjzz黄色片| 欧美久久精品| 国产视频久久久| 色一情一交一乱一区二区三区| 猛男gaygay欧美视频| 亚洲精品自产拍| 欧美图片第一页| 成人羞羞动漫| 久久九九热免费视频| 欧美激情图片小说| 国内精品亚洲| 性欧美长视频免费观看不卡| 欧美日韩精品区| 久久综合九色综合欧美狠狠| 国产福利精品视频| 96亚洲精品久久久蜜桃| 国产伦精品一区二区三区免费迷| 欧美日韩免费观看一区二区三区| 久久久久久久午夜| 亚洲啊v在线| 日本久久精品电影| 手机看片一级片| 蜜桃在线一区| 亚洲缚视频在线观看| 粉嫩av蜜桃av蜜臀av| 国产探花一区二区| 久久亚洲精品一区| 一区二区三区视频免费看| 久久精品国产清高在天天线| 成人在线视频网| 国产喷水福利在线视频| 岛国一区二区三区| 欧美一区二区三区四区夜夜大片| 欧美激情午夜| 亚洲成av人片在www色猫咪| 国产中文字幕免费观看| 韩国精品视频在线观看| 日韩视频在线观看一区二区| 无码人妻精品一区二区三区99不卡| 伊人久久大香线蕉| 毛片精品免费在线观看| 亚洲久久在线观看| 狠狠色综合色综合网络| 九九九九精品| 久草中文在线| 色综合一个色综合亚洲| 日本特黄在线观看| 一区二区三区视频免费观看| 欧美成aaa人片免费看| 日本三级网站在线观看| 久久精品国产在热久久| 国产中文一区二区| gogogo高清在线观看免费完整版| 一区二区免费视频| 成人午夜激情av| 国产伦精品一区二区三区免费优势| 中文在线不卡视频| 久久久久久少妇| 国产精品羞羞答答xxdd| 日本在线观看不卡| av在线资源| 91精品午夜视频| 精品无码人妻一区二区免费蜜桃| 欧美激情一级片一区二区| 国产精品日日做人人爱| 天堂а√在线8种子蜜桃视频| 亚洲视频香蕉人妖| 浓精h攵女乱爱av| 亚洲aa在线| 欧美日韩xxxxx| 国产又大又粗又长| 欧美国产精品中文字幕| 国产91美女视频| 国产精品久久久久久久久久白浆 | 无码少妇精品一区二区免费动态| 亚洲激情二区| 国产精品国产精品| 日本在线观看高清完整版| 欧美日本一区二区三区四区| 日本一卡二卡在线播放| 三级影片在线观看欧美日韩一区二区| 国产日韩欧美亚洲一区| 色婷婷视频在线观看| 7777女厕盗摄久久久| 成人黄色短视频| 奇米色一区二区三区四区| 欧美中日韩免费视频| 天堂中文最新版在线中文| 亚洲第一中文字幕在线观看| 精品视频一区二区在线观看| 国产电影精品久久禁18| 日韩欧美一级在线| 亚洲午夜免费| 久久久久久久久久久久av| 午夜精品在线播放| 一区二区三区欧美久久| 中文字幕乱码在线人视频| 久久精品欧美一区| 91亚洲精品久久久久久久久久久久| 免费黄色在线| 欧美美女一区二区三区| 内射一区二区三区| 成人综合婷婷国产精品久久蜜臀 | 国产精品偷拍| 亚洲成人教育av| 九九热在线免费观看| 91色porny蝌蚪| 欧美少妇性生活视频| 国产精品三级| 国产精品电影久久久久电影网| 国产高清视频在线| 欧美日韩的一区二区| 一区二区三区影视| 国产高清一区日本| 波多野结衣之无限发射| 亚洲精品小区久久久久久| 国产精品久久久久久久久久小说 | 中文字幕乱妇无码av在线| 国产精品九九| 欧美一区1区三区3区公司| av成人亚洲| 久久99精品久久久久久噜噜| 天堂v视频永久在线播放 | 亚洲国产精品无码久久| 精品成人在线视频| 91精品久久久久久久久久久久| 精品一区二区三区视频| 欧美一区二区激情| 国产精品亚洲片在线播放| 成人a在线观看| yellow字幕网在线| 一本一本久久a久久精品牛牛影视 一本色道久久综合亚洲精品小说 一本色道久久综合狠狠躁篇怎么玩 | 91精品久久香蕉国产线看观看| gogo高清午夜人体在线| 国产亚洲精品美女久久久久| 99久久久无码国产精品免费| 精品久久中文字幕| 亚洲欧美卡通动漫| proumb性欧美在线观看| 亚洲欧美视频二区| 亚洲第一网站| 一区二区三区av在线| 大桥未久女教师av一区二区| 国产精品久久久久久久久久久久久久| 午夜伦理在线视频| 夜夜嗨av色综合久久久综合网| 亚洲精品久久久久久久久久 | 亚洲人成精品久久久久久 | 校花撩起jk露出白色内裤国产精品| 国产精品久久久久av| 欧美videossex| 自拍视频国产精品| 男男电影完整版在线观看| 日韩视频免费直播| 在线播放国产一区| 欧美性xxxxxxxxx| 九九九在线视频| 国产精品久久久久久户外露出| 亚洲精品乱码久久久久久蜜桃图片| 蜜臀久久99精品久久久画质超高清| 久艹视频在线免费观看| 亚洲成人免费| 影音先锋在线亚洲| japanese国产精品| 久久伊人资源站| 91久久精品无嫩草影院| 国产一区二区在线播放| 国产日韩电影| 久久久久久久爱| 日本一级理论片在线大全| 上原亚衣av一区二区三区| 青青草在线免费视频| 亚洲精品一区二区三区福利| 国产乱淫a∨片免费观看| 在线观看91视频| 丁香社区五月天| 一本大道久久a久久综合| 日韩乱码一区二区| 亚洲午夜激情网站| 久久久久亚洲AV| 亚洲精品免费电影| 午夜精品福利在线视频| 国产精品久久久久久久久免费桃花 | 中文字幕一区二区人妻痴汉电车 | 每日在线更新av| 亚洲午夜电影| 亚洲国产成人精品无码区99| 在线午夜精品| 欧美黄色免费影院| 久久精品网址| 嫩草av久久伊人妇女超级a| 翔田千里一区二区| 成人三级视频在线播放| 日韩精品一二区| wwwwww.色| 久久99国产精品免费| 一道本在线免费视频| 久久se这里有精品| 天天综合成人网| 国产精品一卡二卡| 女同性恋一区二区三区| www成人在线观看| 亚洲精品国产一区黑色丝袜| 亚洲国产精品成人综合色在线婷婷| 久久久久久久毛片| 中文字幕一区二区三区在线观看| 伊人在线视频观看| 亚洲综合免费观看高清在线观看| 精品少妇theporn| 日韩欧美大尺度| а中文在线天堂| 欧美人成免费网站| www.午夜激情| 亚洲久久久久久久久久久| 大地资源中文在线观看免费版| 一夜七次郎国产精品亚洲| 国产日产一区二区| 韩剧1988在线观看免费完整版| 自拍一区在线观看| 国产精品亚洲第一区| 一区二区视频| 欧美乱偷一区二区三区在线| 欧美成人自拍| 国产片侵犯亲女视频播放| 亚洲一区二区动漫| 永久免费的av网站| 成人av先锋影音| 亚洲第一综合网| 亚洲免费伊人电影| 国产精品视频免费播放| 欧美三级电影网站| 黑人精品一区二区| 揄拍成人国产精品视频| 另类视频在线| 国产精品露脸av在线| 午夜视频一区二区在线观看| 欧美一级二级三级九九九| 欧美在线不卡| 中文字幕第36页| 成人一区二区三区视频| 永久免费观看片现看| 亚洲国产精品久久久久婷婷884| 成人一级免费视频| 精品国产乱码久久久久久夜甘婷婷 | 欧美一区=区三区| 精选一区二区三区四区五区| 99精品电影| 黄在线观看网站| 国产大片一区二区| 妖精视频在线观看免费| 亚洲大片一区二区三区| 国产美女免费视频| 亚洲全黄一级网站| 福利写真视频网站在线| 国产免费亚洲高清| 在线日本制服中文欧美| 乱熟女高潮一区二区在线| 久久成人羞羞网站| 永久免费成人代码| 午夜精品久久久久久久蜜桃app| 国产又粗又猛又爽又黄视频| 国产亚洲xxx| 国产精品vvv| av一区观看| 国产高清久久| 九九热99视频| 久久久久九九视频| 五月天激情国产综合婷婷婷| 精品久久一区二区| caopeng在线| 91久久精品视频| 日韩电影免费网址| 热久久精品国产| 久久亚洲一区二区三区四区| 日韩熟女精品一区二区三区| 日韩一二在线观看| 伊人影院在线视频| 91色视频在线导航| 99精品网站| 久久久精品高清| 国产精品久久久久aaaa樱花| 最近中文字幕在线视频| 国产亚洲xxx| www.国产精品| 欧美综合激情| 久久久久久一区二区| 中文字幕国产综合| 91久久精品网| 91社区在线| 国产久一一精品| 国产精品福利在线观看播放| 国产探花在线看| 综合av第一页| 成人1区2区3区| 欧美激情奇米色| 久久91在线| www.四虎成人| 亚洲国产高清不卡| 伊人亚洲综合网| 另类色图亚洲色图| 51精品国产| 成人在线免费观看av| 久久影院视频免费| 国产裸体美女永久免费无遮挡| 自拍偷拍亚洲在线| 欧美专区一区| 无罩大乳的熟妇正在播放| 久久欧美中文字幕| 姑娘第5集在线观看免费好剧| 最新国产精品亚洲| 伊人www22综合色| 日本福利视频在线| 欧美国产欧美亚州国产日韩mv天天看完整| 国产91av在线播放| 欧美日韩国产成人在线| 免费看成人人体视频| 激情综合网俺也去| 最新不卡av在线| 污视频在线免费观看| 国产精品自产拍在线观| 女人色偷偷aa久久天堂| 久久久午夜精品福利内容| 日本韩国一区二区| 国产一区久久精品| 久久久人人爽| 久久精品国产99| 日韩精品一区二区av| 色偷偷综合社区| 乱亲女h秽乱长久久久| 一区二区三区网址| 亚洲小说欧美激情另类| 国产小视频免费在线网址| 91精品国产综合久久香蕉| 99热精品在线| 黑人狂躁日本娇小| 亚洲精品动漫100p| 色婷婷成人网| 国产又黄又大又粗视频| 亚洲特黄一级片| 神马精品久久| 91九色在线观看| 久久午夜精品一区二区| 2018天天弄| 在线视频亚洲欧美| 加勒比视频一区| 在线免费黄色小视频|