2013-05-13 31 views
5

Nếu tôi hiểu cách trình biên dịch C++ xử lý các biến cục bộ thì IsShutdownInProgress() không cần bất kỳ khóa nào vì biến tĩnh tĩnh shutdownInProgress sẽ được đặt trên ngăn xếp. Tôi có đúng không?Mutex khi trả về giá trị đối tượng

class MyClass 
{ 
    private: 
     // Irrelevant code commented away 
     static pthread_mutex_t mutex; 
     static bool shutdownInProgress; 
    public: 
     static void ShutdownIsInProgress() 
     { 
      pthread_mutex_lock(mutex); 
      shutdownInProgress = true;     
      pthread_mutex_unlock(mutex); 
     } 

     static bool IsShutdownInProgress() 
     { 
      // pthread_mutex_lock(mutex); 
      // pthread_mutex_unlock(mutex); 
      return shutdownInProgress; 
     } 
} 

Trả lời

7

Am I chính xác?

No. Điều này sẽ tạo một bản sao để trả lại; nhưng đọc nó để làm cho bản sao đó mà không đồng bộ hóa sẽ cung cấp cho cuộc đua dữ liệu , với hành vi không xác định. Bạn sẽ cần phải thực hiện một bản sao cục bộ của nó với các mutex khóa:

static bool IsShutdownInProgress() 
{ 
    pthread_mutex_lock(mutex); 
    bool result = shutdownInProgress; 
    pthread_mutex_unlock(mutex); 
    return result; 
} 

hay, sử dụng dễ bị lỗi kiểu khóa RAII ít:

static bool IsShutdownInProgress() 
{ 
    lock_guard lock(mutex); 
    return shutdownInProgress; 
} 

Trong C++ 11, có lẽ bạn xem xét std::atomic<bool> để thuận tiện hơn và có lẽ hiệu quả hơn, truy cập vào các loại đơn giản từ nhiều luồng.

1

Vâng, nó cần một khóa mô hình bộ nhớ

C++ 11 của bang bạn có một cuộc đua dữ liệu nếu có đề đang viết một giá trị cùng một lúc như một thread đọc nó. Điều này là do cả đọc và/hoặc ghi có thể không phải là nguyên tử.

Trong trường hợp này, bạn sẽ trả về cục bộ từ hàm, nhưng để có được trình biên dịch cục bộ cần sao chép giá trị trong shutdownInProgress, có thể đồng thời bị thay đổi bởi một chuỗi khác gọi ShutdownIsInProgress().

Một cách dễ dàng để giải quyết này là để đảm shutdownInProgress một nguyên tử:

static std::atomic<bool> shutdownInProgress; 

Nếu bạn thực hiện nó nguyên tử, bạn không cần bất kỳ ổ khóa ở tất cả cho một trong hai chức năng

2

Điều kiện chủng tộc không liên quan đến việc biến có nằm trên heap hoặc trên ngăn xếp hay không. Điều kiện chủng tộc là khi một luồng đang sửa đổi một biến (vị trí bộ nhớ) và một luồng khác đang đọc hoặc sửa đổi cùng một biến. Không có gì đảm bảo rằng việc sửa đổi một bool là nguyên tử để mã được đăng có điều kiện chủng tộc và do đó hành vi không xác định.

Một sửa chữa sẽ được lưu trữ giá trị của bool khi mutex được tổ chức và trả lại biến:

static bool IsShutdownInProgress() 
{ 
    pthread_mutex_lock(&mutex); 
    bool result = shutdownInProgress; 
    pthread_mutex_unlock(&mutex); 
    return result; 
} 

C++ 11 giới thiệu std::mutexstd::lock_guard mà có thể được sử dụng và việc sử dụng các lock_guard sẽ tránh được những yêu cầu của một biến tạm để lưu trữ các giá trị bool sự trở lại:

static std::mutex mtx_; 
static bool IsShutdownInProgress() 
{ 
    std::lock_guard<std::mutex> lk(mtx_); 
    return shutdownInProgress; 
} 

C++ 11 cũng giới thiệu std::atomic<> rằng sẽ đảm bảo m odification là nguyên tử và tránh sự cần thiết cho một khóa rõ ràng:

static std::atomic<bool> shutdownInProgress; 
static bool IsShutdownInProgress() 
{ 
    return shutdownInProgress; 
} 

Nếu C++ 11 là không có sẵn cho boost::atomic được giới thiệu vào v1.53.0 và thúc đẩy cũng có tương đương boost::mutex and boost::lock_guard.

Các vấn đề liên quan