2013-02-18 81 views
2

看整個類:同步在C++ 11

class Logger { 
public: 
    void log(string& msg){ 
     //lock for all instances 
     cout << "[" << tag << "] " << msg; 
     //unlock 
    } 
private: 
    string tag; 

}; 

什麼是全班(未實例)同步,以便在最簡單的方法的不同實例Logger(在不同的線程中)按順序寫入cout(並非全部一次)?

+2

static/global mutex? – niXman 2013-02-18 08:21:47

+2

應該添加一個互斥類型的'static'成員。 – Angew 2013-02-18 08:22:37

+0

讓自己成爲一個同步的'std :: cout'。 – Xeo 2013-02-18 08:22:46

回答

7

的常用方法,用互斥鎖:

#include <mutex> 

class Logger { 
public: 
    void log(string& msg) 
    { 
     // Lock for all instances 
     std::lock_guard<std::mutex> lock(coutMutex); 

     cout << "[" << tag << "] " << msg; 

     // Unlocking happens automatically since the lock 
     // gets destroyed here. 
    } 

private: 
    string tag; 
    static std::mutex coutMutex; // Don't forget to define this somewhere. 
}; 
+0

這很好,但'cout'保證,通過'<<'推送給它的東西將在多線程應用程序中被打印/刷新? – Queequeg 2013-02-18 12:38:18

+0

@Queequeg在C++ 03中,iostream不是線程安全的(可能是,但標準不會指定它。)在C++ 11中,它是(標準保證不存在會導致流式腐敗的競爭條件)。但是,輸出的順序不能保證,除非你專門同步它。所以簡短的回答是:是的。如果你同步,那麼'cout <<「12」'在一個線程中,'cout <<「34」'在另一個線程中不會導致像'1324'打印的東西。 – 2013-02-18 17:34:24

2

最簡單的方式做到這一點:

class Logger { 
public: 
    void log(std::string& msg){ 
    //lock for all instances 
    { std::unique_lock<std::mutex> locker(_mut); // or std::lock_guard<std::mutex> locker(_mut); 
     std::cout << "[" << tag << "] " << msg; 
    } //unlock 
private: 
    std::string tag; 
    static std::mutex _mut; 
}; 
2

短版:寫一個同步的包裝,包裝std::cout,然後使用同步cout到寫。

龍版本:

#include <mutex> 

template<typename T> 
struct Synchronized { 
    explicit Synchronized(T& t_):t(t_) {} 

    template<typename Functor> 
    auto operator()(Functor&& f) const->decltype(f(t)) { 
    std::lock_guard<std::mutex> guard(myMutex); 
    return f(t); 
    } 
// I could implement these, but I'm lazy: 
    Synchronized& operator=(Synchronized const&) = delete; 
    Synchronized& operator=(Synchronized &&) = delete; 
    Synchronized(Synchronized const&) = delete; 
    Synchronized(Synchronized &&) = delete; 
private: 
    mutable T& t; 
    mutable std::mutex myMutex; 
}; 


// in "sync_cout.h" 
extern Synchronized<std::ostream> sync_cout; 

// in "sync_cout.cpp" 
Synchronized<std::ostream> sync_cout(std::cout); 

// In "logger.h" 

// #include "sync_cout.h" 
class Logger { 
public: 
    void log(string& msg){ 
    sync_cout([&](std::ostream& os) { 
     os << "[" << tag << "] " << msg; 
    }); 
    } 
private: 
    string tag; 

}; 

(從Herb被盜上述任何錯誤都是我自己的,不是香草的。)

對於性能優越,上面的鏈接還包括異步非阻塞包裝。

0
//use c++ 11 mutex 

class CircularQueue 
{ 
protected: 
    int * data; 
    int head; 
    int tail; 
    int size; 
    std::mutex queueMutex; 
public: 
    CircularQueue(void); 
    int dequeue(); 
    void enqueue(int x); 
    void initialize(int size); 
    virtual ~CircularQueue(void); 
}; 



CircularQueue::CircularQueue(void) 
{ 
    data = 0x0; 
    head = -1; 
    tail = -1; 
    size=0; 
} 

int CircularQueue::dequeue() 
{ 
    if(tail == head) 
    { 
     throw "empty queue!"; 
    } 
    std::lock_guard<std::mutex> lock(queueMutex); 

    int result = data[head]; 
    head ++; 
    if(head >= size) 
    { 
     head =head % size; 
    } 

    return result; 
} 


void CircularQueue::enqueue(int x) 
{ 

    std::lock_guard<std::mutex> lock(queueMutex); 
    data[tail] = x; 
    tail ++; 
    if(tail >= size) 
    { 
     tail = tail % size; 
    } 
    if(tail == head) 
    { 
     throw "overflow!"; 
    } 
} 

void CircularQueue::initialize(int size) 
{ 
    data = new int[size]; 
    head = 0; 
    tail = 0; 
    this->size = size; 
} 

CircularQueue::~CircularQueue(void) 
{ 
    delete [] data; 
}