2012-03-17 46 views
6

Tôi có một tập hợp các hàm C++:Operations nguyên tử trong C++

funcB(){}; 
funcC(){}; 
funcA() 
{ 
    funcB(); 
    funcC(); 
} 

Bây giờ tôi muốn làm funcA nguyên tử, tức là funcBfuncC cuộc gọi bên funcA nên được thực hiện nguyên tử. Có bất kì cách nào để đạt được điều này không?

+1

Bạn có thể giải thích ý bạn bằng "thực thi nguyên tử" không? Có vẻ như bạn chỉ muốn một 'std :: mutex'. – Potatoswatter

+1

Đó có lẽ là những gì anh ấy thực sự muốn. – Joshua

+1

Có lẽ ai đó phải hiển thị cho anh ta cú pháp thích hợp để sử dụng 'std :: mutex'. Có lẽ anh ta không biết. Tôi sẽ không biết làm thế nào để sử dụng một mutex trong một số ngôn ngữ khác. Lời giải thích có lẽ nên bao gồm giả định rằng toàn bộ chương trình phải tôn trọng mutex. I E. thread B vẫn có thể gọi funcB và funcC ngay cả khi luồng A làm như vậy dưới một mutex, trừ khi lập trình viên cấm nó thông qua thiết kế. –

Trả lời

6

Nói chung, KHÔNG. Các hoạt động nguyên tử được xác định rất chính xác. Những gì bạn muốn là một semaphore hoặc một mutex.

+0

Xin lưu ý rằng trong khi câu trả lời này nói đúng, câu trả lời của Robᵩ hữu ​​ích hơn đối với người dùng744829. – Joshua

11

Một cách bạn có thể thực hiện việc này là sử dụng các tính năng mới (C++ 11) std::mutexstd::lock_guard.

Đối với mỗi tài nguyên được bảo vệ, bạn tạo nhanh một đơn toàn cầu std::mutex; mỗi thread sau đó khóa mutex đó, vì nó đòi hỏi, bởi việc tạo ra một std::lock_guard:

#include <thread> 
#include <iostream> 
#include <mutex> 
#include <vector> 

// A single mutex, shared by all threads. It is initialized 
// into the "unlocked" state 
std::mutex m; 

void funcB() { 
    std::cout << "Hello "; 
} 
void funcC() { 
    std::cout << "World." << std::endl; 
} 
void funcA(int i) { 

    // The creation of lock_guard locks the mutex 
    // for the lifetime of the lock_guard 
    std::lock_guard<std::mutex> l(m); 

    // Now only a single thread can run this code 
    std::cout << i << ": "; 
    funcB(); 
    funcC(); 

    // As we exit this scope, the lock_guard is destroyed, 
    // the mutex is unlocked, and another thread is allowed to run 
} 

int main() { 
    std::vector<std::thread> vt; 

    // Create and launch a bunch of threads 
    for(int i =0; i < 10; i++) 
    vt.push_back(std::thread(funcA, i)); 

    // Wait for all of them to complete 
    for(auto& t : vt) 
    t.join(); 
} 

Ghi chú:

  • Trong ví dụ của bạn một số mã không liên quan đến funcA có thể gọi hoặc funcB hoặc funcC mà không tôn vinh khóa funcA.
  • Tùy thuộc vào cách chương trình của bạn được cấu trúc, bạn có thể muốn quản lý toàn bộ thời gian của mutex khác nhau. Ví dụ, nó có thể muốn trở thành một thành viên của lớp bao gồm funcA.
1

Nếu bạn đang sử dụng GCC 4.7 hơn bạn có thể sử dụng mới giao dịch Memory tính năng để làm như sau:

bộ nhớ giao dịch được thiết kế để làm cho chương trình với chủ đề đơn giản hơn, trong việc tiếp cận đồng bộ hóa đặc biệt để chia sẻ dữ liệu giữa một số chủ đề sử dụng giao dịch. Cũng như với cơ sở dữ liệu, giao dịch là một đơn vị công việc hoàn thành toàn bộ hoặc không có hiệu lực nào (tức là, các giao dịch thực thi nguyên tử). Hơn nữa, các giao dịch được tách biệt với nhau sao cho mỗi giao dịch nhìn thấy một bộ nhớ nhất quán về bộ nhớ.

Hiện tại, giao dịch chỉ được hỗ trợ trong C++ và C dưới dạng bảng sao kê giao dịch, biểu thức giao dịch và giao dịch chức năng. Trong ví dụ sau, cả a và b sẽ được đọc và sự khác biệt sẽ được ghi vào c, tất cả các nguyên tử và phân lập từ các giao dịch khác:

__transaction_atomic { c = a - b; } 

Do đó, thread khác có thể sử dụng đoạn mã sau để đồng thời cập nhật b không bao giờ gây ra c để giữ một giá trị âm (và mà không cần phải sử dụng các cấu trúc đồng bộ khác như ổ khóa hoặc C++ 11 Atomics):

__transaction_atomic { if (a > b) b++; } 

ngữ nghĩa chính xác của các giao dịch được quy định tại điều khoản của C++ 11/Mô hình bộ nhớ C1X (xem bên dưới để biết liên kết đến đặc điểm kỹ thuật). Nói chung, các giao dịch cung cấp các đảm bảo đồng bộ hóa tương tự như những gì sẽ được đảm bảo khi sử dụng một khóa toàn cầu duy nhất làm bảo vệ cho tất cả các giao dịch. Lưu ý rằng giống như các cấu trúc đồng bộ hóa khác trong C/C++, các giao dịch dựa vào một chương trình không có dữ liệu (ví dụ, một ghi không truyền dịch đồng thời với một giao dịch được đọc đến cùng một vị trí bộ nhớ là một cuộc đua dữ liệu).

Thông tin khác: http://gcc.gnu.org/wiki/TransactionalMemory

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