2012-04-24 102 views
12

Tôi đang cố gắng một chương trình:Số async/tương lai trong C++ 11

#include <iostream> 
#include <thread> 
#include <future> 

int foo() { 
    return 0; 
} 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 10000; ++i) { 
    auto f = std::async(foo); 
    f.get(); 
    } 
    return 0; 
} 

Compiler VS11 x64.

tích xây dựng:

cl /EHsc /Zi async.cpp && async 

Đối với tôi chương trình này đụng độ. Tôi nghi ngờ, có một giới hạn về số lượng tương lai thể chất chạy cùng một lúc. Nếu tôi giảm số lần lặp lại thành một vài đơn đặt hàng, nó sẽ hoạt động.

Vì vậy, hai câu hỏi:

  1. Có giới hạn của thực sự chạy tương lai trong C++ 11?

  2. Tại sao mã này gặp sự cố? Nếu tôi rõ ràng làm "get()" ngay sau "async()", nó phải hoàn thành tương lai trước lần lặp tiếp theo, có nghĩa là chỉ một tương lai chạy tại một thời điểm.

CẬP NHẬT

tôi đã đơn giản hóa mã để:

#include <future> 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 1000000; ++i) { 
    auto f = std::async([](){ return 0; }); 
    f.get(); 
    } 
    return 0; 
} 

Và nó vẫn bị treo đối với tôi. Nó không ném, tôi đã kiểm tra điều đó. Nhưng bây giờ tôi có một vết đống có thể nhìn thấy:

async.exe!_Mtx_unlock(_Mtx_internal_imp_t * * mtx) Line 229 C++ 
async.exe!std::_Mtx_unlockX(_Mtx_internal_imp_t * * _Mtx) Line 84 C++ 
async.exe!std::_Mutex_base::unlock() Line 47 C++ 
async.exe!std::unique_lock<std::mutex>::~unique_lock<std::mutex>() Line 284 C++ 
async.exe!std::_Associated_state<int>::_Set_value(int && _Val, bool _At_thread_exit) Line 358 C++ 
async.exe!std::_Packaged_state<int __cdecl(void)>::_Call_immediate() Line 569 C++ 
async.exe!std::_Async_state<int>::`std::U_Nil::ain::ain'::`3'::<lambda_A200A86DFF9A63A1>::operator()() Line 700 C++ 
[email protected]@[email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@QEAAXXZ() Line 420 C++ 
[email protected][email protected][email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected][email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@UEAAXXZ() Line 217 C++ 
async.exe!std::_Func_class<void,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>::operator()() Line 1056 C++ 
async.exe!std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>::_ApplyX<Concurrency::details::_Unit_type>() Line 420 C++ 
async.exe!std::_Func_impl<std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>,std::allocator<std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> >,Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_call() Line 217 C++ 
async.exe!std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B>::operator()() Line 325 C++ 
async.exe!Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> >::operator()() Line 72 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_InvokeBridge<Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > >(Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > * _PChore) Line 4190 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_UnstructuredChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 275 C++ 
async.exe!Concurrency::details::_PPLTaskChore::_DeletingChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 78 C++ 
async.exe!Concurrency::details::InternalContextBase::ExecuteChoreInline(Concurrency::details::WorkItem * pWork) Line 1600 C++ 
async.exe!Concurrency::details::InternalContextBase::Dispatch(Concurrency::DispatchState * pDispatchState) Line 1704 C++ 
async.exe!Concurrency::details::FreeThreadProxy::Dispatch() Line 191 C++ 
async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain(void * lpParameter) Line 173 C++ 
kernel32.dll!0000000076df652d() Unknown 
ntdll.dll!0000000076f2c521() Unknown 

và chủ đề:

Unflagged  1864 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f518ca Normal 
Unflagged  10964 0 Main Thread Main Thread async.exe!do_signal Normal 
Unflagged  7436 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f52c1a Normal 
Unflagged  10232 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged > 10624 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!_Mtx_unlock Normal 
Unflagged  4756 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged  11100 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::InternalContextBase::WaitForWork Normal 
Unflagged  6440 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!std::vector<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64>,std::allocator<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64> > >::_Tidy Normal 

Tôi đang sử dụng VS 11.0.40825.2 PREREL.

+3

Nghe như lỗi trình biên dịch. –

+0

Tôi không tin rằng yêu cầu này sẽ khởi chạy một chuỗi khác, nó chỉ là một thực thi bị trì hoãn. Ví dụ: foo sẽ được gọi khi dòng f.get() được thực hiện. – alanxz

+1

Trình gỡ lỗi sẽ giúp bạn hiểu tại sao mã bị treo. Tôi sẽ thử điều đó trước khi giả sử trình biên dịch bị hỏng. –

Trả lời

4
  1. Rõ ràng có giới hạn triển khai, giống như có giới hạn về mức độ lớn của mảng. std :: async có thể báo hiệu một lỗi 'resource_unavailable_try_again' nếu chính sách khởi chạy là lauch :: async và hệ thống không thể bắt đầu một chuỗi mới. Nhưng bạn không nhận được lỗi này.

  2. Chương trình không bị lỗi và không cho tôi (VS11 x64, bản phát hành, cùng nguồn và dòng lệnh).

    Tôi tin rằng ngay cả khi không có .get() thì chương trình sẽ không có nhiều thao tác không đồng bộ cùng một lúc. Bạn gán tương lai cho một biến cục bộ trong tương lai bị phá hủy mỗi vòng lặp lặp lại, buộc hoạt động không đồng bộ hoàn tất trước khi bạn bắt đầu một phép lặp khác trong vòng lặp tiếp theo.

1

Cố gắng kèm theo mã của bạn trong main() với một try-catch và kiểm tra xem nó ném một std :: ngoại lệ. Điều này có thể đưa ra một gợi ý. Bên cạnh đó, C++ 11 trong VS vẫn là bản beta.

+6

Và beta là khi báo cáo lỗi có giá trị nhất. –

1
  1. Không, tiêu chuẩn không nói giới hạn về thư viện hỗ trợ luồng (bao gồm chủ đề, tương lai, v.v.).

  2. Tùy thuộc vào chất lượng triển khai của thư viện hỗ trợ luồng và API cơ bản.Như bạn nói f.get() chờ cho việc biên dịch nhiệm vụ (hành vi này yêu cầu C++ Standard). Khi việc triển khai thư viện có thể KHÔNG sử dụng lại các tài nguyên như xử lý luồng của API, nó có thể gây ra sự thiếu hệ thống và sự sụp đổ của chương trình. Đó là chất lượng thực hiện thư viện.

0

Nếu bạn đang sử dụng g ++ với tùy chọn std = C++ 11, hãy đảm bảo bạn có phiên bản gần đây và liên kết với pthread.

Ví dụ, trên CodingGround biên soạn mặc định mà bạn nhận được (với nút Compile) là:

g++ -std=c++11 -o main *.cpp 

và nó không thành công với "gì(): Lỗi không xác định -1". Nhưng bạn có thể tự thêm -lpthread để lệnh biên soạn:

g++ -std=c++11 -o main -lpthread *.cpp 

và nó sẽ chỉ làm việc tốt.