精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

天天操天天色综合| 国产乱码精品1区2区3区| 亚洲国产精品热久久| 99福利在线观看| 成全电影播放在线观看国语| 久久精品国产99久久6| 久久91精品国产91久久久| 老司机免费视频| 国产91精品在线| 一区二区成人在线视频| 快播日韩欧美| 在线免费观看中文字幕| 韩日成人av| 国产亚洲精品日韩| 久久久久亚洲av片无码v| 天堂中文最新版在线中文| 自拍偷自拍亚洲精品播放| 久久国产欧美精品| a级片在线播放| 日韩国产欧美在线观看| 久久久亚洲天堂| 99精品全国免费观看| 欧美日韩麻豆| 日韩一区二区三区免费看| 成人羞羞国产免费网站| 日本色护士高潮视频在线观看| 国产婷婷一区二区| 国产精华一区二区三区| 一级全黄少妇性色生活片| 免费亚洲一区| 午夜精品国产精品大乳美女| 蜜臀久久精品久久久用户群体| 久久91麻豆精品一区| 亚洲成年人在线| 污视频在线观看免费网站| 亚洲国产尤物| 一本到一区二区三区| 日本午夜激情视频| 日本伦理一区二区| 亚洲女同一区二区| 国产91av视频在线观看| 成人av一区| 欧美国产精品劲爆| 日本一区二区精品视频| 午夜视频在线免费播放| 成人av免费在线观看| 91在线观看网站| 99国产精品久久久久久久成人 | 欧美激情综合五月色丁香| 国产一区二区精品免费| 乱精品一区字幕二区| 国产高清亚洲一区| 99se婷婷在线视频观看| www.日日夜夜| 国产成人一区在线| 91gao视频| 亚洲国产精品久久久久久6q | 色婷婷av一区二区三区软件| 黄色一级视频在线播放| 超清av在线| 亚洲成人动漫一区| 可以在线看的av网站| 涩涩视频在线免费看| 欧美日韩激情视频| www黄色av| 忘忧草在线www成人影院| 在线亚洲免费视频| 色哟哟精品视频| 欧美一区二区三区婷婷| 欧美美女视频在线观看| 久久精品一卡二卡| 亚洲精品影片| 日韩av影视综合网| 自拍偷拍视频亚洲| 久久国产精品亚洲人一区二区三区 | 亚洲另类中文字| 欧美黄网在线观看| 韩日毛片在线观看| 日韩欧美在线一区| 中文字幕成人在线视频| 国产欧美88| 精品成人免费观看| 伊人网在线视频观看| 欧美第一精品| 欧美—级a级欧美特级ar全黄| 三级黄色在线视频| 免费观看在线色综合| 亚洲精品欧美一区二区三区| 国产小视频免费观看| 2022国产精品视频| 一本二本三本亚洲码| 超碰在线中文字幕| 精品视频在线免费| 亚洲色图欧美另类| 精品国产一区二区三区小蝌蚪 | 国产精品1234区| 噜噜噜91成人网| 91香蕉电影院| 日本高清中文字幕二区在线| 成人免费在线视频观看| av免费观看国产| 91麻豆精品| 亚洲精品720p| 疯狂撞击丝袜人妻| 久久免费国产| 99高清视频有精品视频| 国产一级网站视频在线| 一区二区三区四区在线播放 | www.欧美视频| 日韩av在线播放资源| 午夜剧场免费在线观看| 午夜影院日韩| 亚洲字幕一区二区| av小片在线| 日韩欧美一区二区三区| 国产精品欧美性爱| 日韩精品一卡| 日本精品久久中文字幕佐佐木| 国产女无套免费视频| 久久嫩草精品久久久精品| 欧美一级中文字幕| 先锋影音一区二区| 国产亚洲成av人片在线观看桃| 久久国产免费观看| 久久精品国产99国产| 欧美污视频久久久| heyzo一区| 91精品婷婷国产综合久久竹菊| 一区二区三区伦理片| 99精品久久久| 国产一区二区三区四区五区在线| 黄色片免费在线观看| 欧美性一级生活| 国产全是老熟女太爽了| a91a精品视频在线观看| 亚洲欧美偷拍卡通变态| 日韩在线视频网站| 国产精品一区无码| 99久久国产免费看| 极品粉嫩国产18尤物| 欧美第一在线视频| 麻豆乱码国产一区二区三区 | 黄色av片三级三级三级免费看| 美女久久一区| 久久久久久久久久久久久久一区| 久久一卡二卡| 欧美成人一区二区三区| 成人在线观看免费完整| 精品在线播放免费| 一区二区不卡在线视频 午夜欧美不卡' | 欧美 日韩 中文字幕| 亚洲免费观看视频| 免费观看黄网站| 国内精品美女在线观看 | 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 亚洲人一二三区| www.污网站| 午夜久久tv| 国产精品免费一区二区三区观看| 青青青国内视频在线观看软件| 日韩一二三区不卡| 久久精品这里只有精品| 成人国产亚洲欧美成人综合网| 男人插女人视频在线观看| 久久亚洲黄色| 日韩美女写真福利在线观看| 国产高清免费av在线| 欧美日韩亚洲国产综合| 日韩福利小视频| 成人免费视频播放| 99蜜桃臀久久久欧美精品网站| 国产精品嫩草影院在线看| 国产精品国产福利国产秒拍| 日本中文在线| 日韩欧美国产综合一区 | 成人午夜精品无码区| 国产综合自拍| 鲁鲁狠狠狠7777一区二区| 不卡av播放| 日韩一区在线视频| www视频在线| 大桥未久av一区二区三区| 亚洲自拍偷拍图| 天天影视色综合| 高h放荡受浪受bl| 黄色成人av网| 成年人在线免费看片| 久久99精品久久只有精品| 亚洲爆乳无码精品aaa片蜜桃| 国产色噜噜噜91在线精品| 国产成人精品优优av| 超碰caoporn久久| 国产视频在线一区二区| 亚洲一区二区视频在线播放| 一区二区三区四区五区视频在线观看 | 久久国产精品72免费观看| 亚洲爆乳无码精品aaa片蜜桃| 免费成人结看片| 91免费欧美精品| 瑟瑟视频在线看| 久久躁日日躁aaaaxxxx| 欧美男男同志| 精品少妇一区二区三区视频免付费| 国产一区二区三区影院| 成人免费在线视频| 免费黄色在线视频| 国产999精品久久| 免费看黄色一级大片| 亚洲精品123区| 天天成人综合网| 免费电影一区二区三区| 亚洲最大福利网| 国模一区二区| 98精品国产自产在线观看| 黄网站视频在线观看| 亚洲男人天堂2019| 空姐吹箫视频大全| 欧美久久久久久久久中文字幕| 精品欧美一区二区三区免费观看| 亚洲精品乱码久久久久| 啪啪一区二区三区| 久久综合色婷婷| 美女日批在线观看| 久久99久久99| 一区二区三区 欧美| 亚洲在线国产日韩欧美| 无码粉嫩虎白一线天在线观看 | 国产成人精品999在线观看| 国产传媒一区二区三区| 激情久久免费视频| 成人国产精品久久久| 欧亚一区二区| 日本免费久久高清视频| 亚洲性色av| 久久久久中文字幕| 精灵使的剑舞无删减版在线观看| 超碰97人人做人人爱少妇| 日韩精品成人av| 日韩在线观看网站| aaa日本高清在线播放免费观看| 日韩国产欧美区| 视频一区二区在线播放| 日韩av在线看| 天天干天天做天天操| 亚洲精品在线免费观看视频| 亚洲国产一二三区| 日韩色在线观看| www三级免费| 亚洲成在人线av| 老熟妇高潮一区二区高清视频| 精品三级在线观看| 日韩有码第一页| 亚洲激情视频在线播放| 五月天婷婷视频| 亚洲欧美国产另类| 黄色网址在线播放| 最近2019年好看中文字幕视频| 一级毛片视频在线| 久久久av免费| eeuss鲁一区二区三区| 午夜精品在线视频| 成人免费网站视频| 国产精品丝袜视频| 婷婷久久免费视频| 国产成人av一区二区三区| 久久亚洲道色| 日韩国产高清一区| 99视频精品视频高清免费| 国产日韩第一页| 国产精品vip| 国产精品50p| 免费一级片91| 精品人妻人人做人人爽夜夜爽| av网站免费线看精品| 欧美 日本 国产| 国产精品久久看| 国产av无码专区亚洲av毛网站| 亚洲主播在线观看| 特级西西444www大精品视频免费看| 色哟哟一区二区| 97av免费视频| 亚洲第一区在线观看| 国产三级在线看| 欧美久久久精品| 亚洲少妇视频| 91美女高潮出水| 丝袜av一区| 中文一区一区三区免费| 亚洲黄网站黄| 鲁一鲁一鲁一鲁一av| 国产99久久久国产精品免费看| 国产免费a级片| 久久久国产一区二区三区四区小说 | 日韩国产成人在线| 日韩亚洲欧美在线观看| 秋霞av在线| 欧美大成色www永久网站婷| caoporn视频在线| 国产日韩av在线| 成人性生交大片免费看中文视频| 色狠狠久久av五月综合| 伊人成人网在线看| 中文久久久久久| 成人99免费视频| 欧美爱爱免费视频| 在线视频综合导航| 天堂中文网在线| 久久艳片www.17c.com| 欧美一区久久久| 国产精品久久亚洲| 国产精品成人av| 亚洲欧美另类动漫| 91在线视频免费91| 欧美日韩激情在线观看| 欧美日韩精品综合在线| 麻豆国产在线播放| 97视频免费观看| 欧美1区2区3| 制服诱惑一区| 蜜桃精品在线观看| 色哟哟精品观看| 都市激情亚洲色图| 高h调教冰块play男男双性文| 久久伊人精品天天| 成人国产精选| 日本10禁啪啪无遮挡免费一区二区| 欧美日本亚洲韩国国产| 精品国产乱码久久久久久1区二区| 国产欧美视频在线观看| 男人天堂2024| 亚洲美女av黄| 欧美男男激情videos| 国产一区二区三区无遮挡| 国产精品草草| 97超碰免费在线观看| 最好看的中文字幕久久| 91精品视频免费在线观看| 亚洲欧洲一区二区三区在线观看| 理论片午夜视频在线观看| 国产精品v欧美精品v日韩| 欧美精品播放| 精品人妻无码中文字幕18禁| 亚洲免费观看高清完整版在线| 亚洲一级av毛片| 久久韩国免费视频| 在线免费观看亚洲| 特色特色大片在线| 国产精品亚洲第一区在线暖暖韩国| 99久久99久久精品国产| 欧美福利电影网| av免费在线网站| 不卡一卡2卡3卡4卡精品在| 欧美日韩理论| 亚洲麻豆一区二区三区| 黄色精品在线看| 你懂的免费在线观看| 国产精品xxxxx| 欧美电影一二区| 亚洲午夜激情影院| 一区二区三区在线免费观看| 国产刺激高潮av| 欧美一级视频一区二区| 欧美在线色图| 天天做天天干天天操| 久久蜜桃av一区精品变态类天堂 | 国产视频丨精品|在线观看| 欧美xx视频| 一区二区三区三区在线| 国产在线播放一区| 日本少妇激情舌吻| 国产亚洲欧洲高清一区| 热久久久久久| 欧美一级欧美一级| 久久九九99视频| 国产日韩欧美视频在线观看| 九九精品在线视频| 色狼人综合干| 依人在线免费视频| 一区二区三区91| 欧美黄色小说| 91精品视频在线免费观看| 亚洲欧洲一区| 一边摸一边做爽的视频17国产| 一本高清dvd不卡在线观看| 岛国中文字幕在线| 精品乱子伦一区二区三区| 免费观看30秒视频久久| 中文字幕在线观看成人| 精品视频一区在线视频| 人人玩人人添人人澡欧美| 青青草视频在线免费播放| 国产精品无遮挡| 日本美女一级视频| 国产精品一区专区欧美日韩| 亚洲国产三级| 日本午夜精品视频| 日韩av在线网| 久久久91麻豆精品国产一区| 激情六月丁香婷婷| 一区二区三区四区高清精品免费观看|