2013-05-21 34 views
11

tôi đã viết đoạn code sau đây để kiểm tra hiểu biết của tôi về std::mutexTại sao khóa một std :: mutex không chặn thread

int main() { 
    mutex m; 
    m.lock(); 
    m.lock(); // expect to block the thread 
} 

Và sau đó tôi nhận được một system_error: device or resource busy. Không phải là lần thứ hai m.lock() phải chặn luồng không?

+2

chỉ có một luồng, tại sao nó hữu ích để chặn nó? – stijn

+0

Chủ đề khác sẽ chặn; không có gì đảm bảo rằng tread mutex-owning sẽ (và trên thực tế phiên bản này tạo ra một lỗi.) – dlev

+2

Nếu cuộc gọi thứ hai đó chặn luồng, luồng sẽ được bỏ chặn như thế nào? –

Trả lời

12

Từ std::mutex:

Một thread gọi không phải sở hữu mutex trước khi gọi khóa hoặc try_lock.

và từ std::mutex::lock:

Nếu khóa được gọi bởi một sợi đã sở hữu mutex, chương trình có thể bế tắc. Ngoài ra, nếu việc triển khai có thể phát hiện bế tắc, điều kiện lỗi resource_deadlock_would_occur có thể được quan sát.

ngoại lệ khoản:

Ném std :: system_error khi lỗi xảy ra, bao gồm cả lỗi từ hệ điều hành cơ bản đó sẽ ngăn chặn khóa từ đáp ứng thông số kỹ thuật của nó. Các mutex không bị khóa trong trường hợp của bất kỳ trường hợp ngoại lệ được ném.

Do đó, nó không được phép chặn chuỗi. Trên nền tảng của bạn, việc triển khai có vẻ như có thể phát hiện khi một luồng đã là chủ sở hữu của một khóa và đưa ra một ngoại lệ. Điều này có thể không xảy ra trên các nền tảng khác, như được nêu trong phần mô tả.

2

(std::mutex đã không được đề cập trong câu hỏi khi tôi đã viết câu trả lời này.)

Nó phụ thuộc vào thư viện mutex và mutex loại mà bạn đang sử dụng - bạn chưa nói với chúng tôi. Một số hệ thống cung cấp "mutex đệ quy" được phép gọi nhiều lần như thế này nếu nó xảy ra từ cùng một luồng (sau đó bạn phải có số mở khóa phù hợp trước khi một luồng khác có thể khóa nó), các thư viện khác coi đây là lỗi và có thể thất bại một cách duyên dáng (như của bạn) hoặc có hành vi không xác định.

+0

std mutex không đệ quy – NoSenseEtAl

+0

ngay cả khi nó được đệ quy, nó sẽ không chặn. Một mutex đệ quy khóa một lần thứ hai và chờ 2 mở khóa. Nó sẽ chặn một chuỗi thứ hai mặc dù. –

+1

Thư viện là thư viện chuẩn C++ 11 và loại mutex là 'std :: mutex'. Đó không phải là một mutex đệ quy; được gọi là 'std :: recursive_mutex'. Và hành vi ở đây không phải đệ quy; nó đưa ra một lỗi khi cố gắng để có được một khóa thứ hai. –

8

Không phải là thứ hai m.lock() phải chặn luồng?

Không, nó mang lại hành vi không xác định. Thứ hai m.lock() phá vỡ yêu cầu này:

C++ 11 30.4.1.2/7 Yêu cầu: Nếu m là loại std::mutex hoặc std::timed_mutex, tiểu trình đang gọi không sở hữu mutex.

Dường như việc triển khai của bạn có thể phát hiện thấy chuỗi cuộc gọi đang sở hữu mutex và đưa ra lỗi; những người khác có thể chặn vô thời hạn hoặc thất bại theo những cách khác.

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