2012-05-28 10 views
5

Tôi mới để Tăng luồng và tôi bị mắc kẹt với cách đầu ra được thực hiện từ nhiều luồng. Tôi có một tăng đơn giản :: thread đếm ngược từ 9 đến 1; chủ đề chính chờ đợi và sau đó in "LiftOff .. !!"BOOST luồng: hành vi cout

#include <iostream> 
#include <boost/thread.hpp> 
using namespace std; 

struct callable { 
    void operator()(); 
}; 

void callable::operator()() { 
    int i = 10; 
    while(--i > 0) { 
     cout << "#" << i << ", "; 
     boost::this_thread::yield(); 
    } 
    cout.flush(); 
} 

int main() { 
    callable x; 
    boost::thread myThread(x); 

    myThread.join(); 

    cout << "LiftOff..!!" << endl; 

    return 0; 
} 

Vấn đề là tôi phải sử dụng câu lệnh "cout.flush()" rõ ràng trong chuỗi để hiển thị đầu ra. Nếu tôi không sử dụng flush(), tôi chỉ nhận được "LiftOff !!" như đầu ra.

Ai đó có thể vui lòng cho biết lý do tôi cần sử dụng lệnh flush() một cách rõ ràng?

+1

Hoạt động theo cách tương tự đối với tôi có hoặc không có 'flush()' (linux 3.0.6, gcc 4.5.3, tăng 1.46). – delicateLatticeworkFever

+0

FWIW, tôi đã thử nghiệm chương trình của bạn trên Win7x64 (MSVC10), và nó in ra các con số mà không cần tuôn ra(). Om bạn thử nghiệm nền tảng nào? –

+0

@KonradRudolph: "điều kiện chủng tộc" sẽ không tạo ra hai bộ đệm đệm riêng biệt, đó là giải thích duy nhất có thể hiểu được vì sao 'endl' trong chính không tuôn ra sau khi chờ đợi trên một chuỗi được nối. (chưa kể: không có "điều kiện chủng tộc" ở đây cả, chỉ có hai chủ đề và một chủ đề chờ đợi.) – delicateLatticeworkFever

Trả lời

5

Đây không phải là chủ đề cụ thể liên quan như cout sẽ đệm thường trên cơ sở mỗi luồng và chỉ đầu ra khi thực hiện quyết định - như vậy trong chuỗi đầu ra sẽ chỉ xuất hiện trên cơ sở thực hiện cụ thể - bằng cách gọi tuôn ra, bạn đang buộc các bộ đệm bị xóa.

Điều này sẽ khác nhau giữa các lần triển khai - thường là sau một số lượng ký tự nhất định hoặc khi một dòng mới được gửi.

Tôi đã tìm thấy rằng nhiều luồng ghi quá dòng hoặc tệp giống nhau hầu như là OK - với điều kiện đầu ra được thực hiện như nguyên tử nhất có thể. Nó không phải là một cái gì đó mà tôi muốn giới thiệu trong một môi trường sản xuất mặc dù vì nó là quá khó đoán.

3

Hành vi này dường như phụ thuộc vào việc triển khai hệ điều hành cụ thể của luồng cout. Tôi đoán rằng các hoạt động ghi trên cout được đệm vào một số bộ nhớ cụ thể trong trường hợp của bạn, và hoạt động flush() buộc chúng được in trên bàn điều khiển. Tôi đoán điều này, kể từ khi endl bao gồm gọi flush() hoạt động và endl trong chức năng chính của bạn không thấy thay đổi của bạn ngay cả sau khi thread đã được tham gia.

BTW sẽ là một ý tưởng tốt để đồng bộ hóa kết quả đầu ra với một luồng được chia sẻ giữa các luồng, nếu không bạn có thể thấy chúng xen kẽ. Chúng tôi làm như vậy cho các lớp ghi nhật ký sử dụng một luồng nền để ghi các thông điệp ghi nhật ký vào luồng được kết hợp.

+0

Tôi sẽ ngạc nhiên khi biết rằng việc triển khai nhiều hơn một bộ đệm stdout cho mỗi quy trình được cho phép theo tiêu chuẩn, vv NHƯNG điều này dường như là giải thích duy nhất có thể. Tất nhiên, chỉ có OP dường như đã quan sát điều này anyway o_O – delicateLatticeworkFever

+0

@ goldilocks: Có đồng ý, hành vi được mô tả làm tôi ngạc nhiên! Nhưng điều này có thể được hệ điều hành cụ thể, ngay cả ngoài việc thực hiện bộ đệm cout/stdout, phải không? Sẽ rất thú vị khi biết hệ điều hành nào được OP sử dụng ... –

+0

Cảm ơn makulik. lý do của bạn nghe có vẻ tốt nhưng nó thực sự đáng sợ nếu cout có một bộ đệm dòng khác nhau cho mỗi chủ đề – Rajat

0

Với độ dài của thư ngắn, không có lý do gì sẽ xuất hiện mà không có sự tuôn ra. (Đừng quên rằng std::endl là tương đương với << '\n' << std::flush.)

0

tôi nhận được hành vi hỏi có và không có tuôn ra (gcc 4.3.2 boost 1.47 Linux RH5)

tôi cho rằng hệ thống Cygwin bạn lựa chọn để thực hiện một số đối tượng với std::cout liên std::streambuf. Điều này tôi giả định là thực hiện cụ thể. Kể từ flush hoặc chỉ kết thúc lực lượng bộ đệm để xả lên chuỗi đầu ra được kiểm soát của hệ điều hành đối tượng cout của chuỗi của bạn vẫn được lưu vào bộ đệm.

Chia sẻ tham chiếu về số ostream giữa các chuỗi sẽ giải quyết được sự cố.