Yep: Boost.Thread thật tuyệt vời và phù hợp với nhu cầu của bạn rất tốt. (Những ngày này, nhiều người nói rằng bạn gần như có thể đếm Boost là chức năng được tích hợp sẵn.)
Vẫn không có lớp nào bạn có thể sử dụng ngoài hộp, nhưng một khi bạn có đồng bộ hóa nguyên gốc trong tầm tay , nó thực sự là khá đơn giản để thực hiện wrapper thread-an toàn của riêng bạn xung quanh, ví dụ, std::stack
. Nó có thể giống như thế này (không phải thực hiện tất cả các phương pháp ...):
template <typename T> class MyThreadSafeStack {
public:
void push(const T& item) {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.push(item);
}
void pop() {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.pop();
}
T top() const { // note that we shouldn't return a reference,
// because another thread might pop() this
// object in the meanwhile
boost::mutex::scoped_lock lock(m_mutex);
return m_stack.top();
}
private:
mutable boost::mutex m_mutex;
std::stack<T> m_stack;
}
Nếu bạn chưa quen với C++, xin vui lòng tìm hiểu về RAII. Có liên quan đến trường hợp này, Boost.Thread có các lớp "scoped lock" để làm cho nó khó chụp ở chân bằng cách quên để nhả khóa.
Nếu bạn đã bao giờ thấy mình viết code như thế này:
void doStuff() {
myLock.lock();
if (!condition) {
reportError();
myLock.unlock();
return;
}
try {
doStuffThatMayThrow();
}
catch (std::exception& e) {
myLock.unlock();
throw e;
}
doMoreStuff();
myLock.unlock();
}
, sau đó bạn nên chỉ nói không, và đi RAII thay vì (cú pháp không trực tiếp từ Boost):
void doStuff() {
scoped_lock lock;
if (!condition) {
reportError();
return;
}
doStuffThatMayThrow();
doMoreStuff();
}
Điểm là khi đối tượng scoped_lock
vượt quá phạm vi, hàm hủy của nó giải phóng tài nguyên - trong trường hợp này là khóa. Điều này sẽ luôn xảy ra, bất kể bạn có thoát khỏi phạm vi bằng cách ném một ngoại lệ hay bằng cách thực hiện câu lệnh return
lẻ mà đồng nghiệp của bạn lén lút thêm vào giữa chức năng của bạn hoặc đơn giản bằng cách đến cuối hàm.
Nếu bạn quan tâm đến tính nguyên tử của lệnh x86 PUSH/POP, hãy đặt câu hỏi riêng biệt - nó không liên quan gì đến C++, sẽ không sử dụng hướng dẫn này để truy cập cấu trúc dữ liệu ngăn xếp. –
Ủy ban bận rộn hơn khi viết các lớp giảng dạy song song về DDJ thay vì làm cho các trừu tượng mô hình bộ nhớ nguyên tử và tốt hơn nhiều cho trình biên dịch bắt buộc trong TR1 (có lẽ không phải trong TR2). Để trả lời: bạn không thực sự đẩy và bật và do đó thay đổi hoàn toàn các thanh ghi trên các luồng nói hiện đang chạy trên các lõi riêng biệt phải không? :-) Bắn tốt, nhưng sẽ không hoạt động .. Bạn không thể làm điều đó không có khóa hoặc ít nhất là không có búa CAS. Đối với các cộng sự của C++: Họ chỉ cần ngồi xuống và xác định và đồng ý về các giao thức mạch lạc hiện có, + để lại một số phạm vi cho những phát triển mới. –
Đối với những người quan tâm, tôi nhìn vào hoạt động nguyên tử và Intel hỗ trợ DCAS thông qua cmpxchg16b. Thật không may AMD chỉ có cmpxchg8b. Không quan trọng đối với tôi, vì tôi đang viết cho các máy Intel :) – bugmenot77