2013-06-03 40 views
11

Tôi đã viết một chương trình đa luồng với pthread, sử dụng mô hình người tiêu dùng sản xuất.Pthread Mutex: pthread_mutex_unlock() tiêu tốn rất nhiều thời gian

Khi tôi sử dụng trình thu thập thông tin Intel VTune để lập hồ sơ chương trình của mình, tôi thấy nhà sản xuất và người tiêu dùng dành nhiều thời gian trên pthread_mutex_unlock. Tôi không hiểu tại sao điều này lại xảy ra. Tôi nghĩ rằng chủ đề có thể chờ đợi một thời gian dài trước khi họ có thể có được một mutex, nhưng phát hành một mutex nên được nhanh chóng, phải không?

Ảnh chụp nhanh bên dưới là từ Intel VTune. Nó cho thấy các mã mà người tiêu dùng cố gắng lấy một mục từ bộ đệm và thời gian được tiêu thụ bởi mỗi dòng mã.

Câu hỏi của tôi là tại sao pthread_mutex_unlock có chi phí như vậy? Có phải vấn đề với bản thân mutex pthread hay bằng cách tôi sử dụng nó? enter image description here

+0

Mở khóa một mutex có thể chậm nếu có nhiều tranh cãi về mutex đó, bởi vì một phần công việc mở khóa đang đánh thức mọi chuỗi đang chờ trên mutex. – caf

+6

Tôi nghĩ rằng sẽ rất thú vị khi xem kết quả nếu bạn di chuyển lệnh 'pthread_mutex_unlock()' bên trên lệnh gọi đến 'pthread_cond_signal()'. Không có yêu cầu để giữ mutex trong khi báo hiệu biến điều kiện (chỉ khi chờ đợi trên nó), và tôi nghi ngờ rằng những gì xảy ra là tín hiệu gây ganh đua trên mutex vì thread được phát hành ngay lập tức cố gắng để có được mutex, mà chuỗi tín hiệu vẫn giữ. –

+2

@MichaelBurr Điểm tốt! Tôi thử nghiệm với đề xuất của bạn và chương trình nhanh hơn khoảng 40% ngay bây giờ. –

Trả lời

2

Hàm pthread_mutex_unlock() sẽ giải phóng đối tượng mutex được tham chiếu bởi mutex. Tuy nhiên, cách thức mà một mutex được phát hành phụ thuộc vào thuộc tính type của mutex. Nếu có chủ đề bị chặn trên đối tượng mutex được tham chiếu bởi mutex khi pthread_mutex_unlock() được gọi, dẫn đến mutex trở nên có sẵn, chính sách lập lịch sẽ xác định chuỗi nào sẽ có được mutex.

Nếu loại mutex là PTHREAD_MUTEX_NORMAL, phát hiện khóa chết sẽ không được cung cấp. Cố gắng để relock mutex gây ra bế tắc. Nếu một chuỗi cố gắng mở khóa một mutex mà nó không bị khóa hoặc một mutex được mở khóa, các kết quả hành vi không xác định.

Nếu loại mutex là PTHREAD_MUTEX_ERRORCHECK, thì việc kiểm tra lỗi sẽ được cung cấp. Nếu một chuỗi cố gắng để relock một mutex rằng nó đã bị khóa, một lỗi sẽ được trả về. Nếu một chuỗi cố gắng mở khóa một mutex mà nó không bị khóa hoặc một mutex được mở khóa, một lỗi sẽ được trả về.

Nếu loại mutex là PTHREAD_MUTEX_RECURSIVE, thì mutex sẽ duy trì khái niệm về tổng số khóa. Khi một chuỗi thành công mua lại một mutex lần đầu tiên, số lượng khóa sẽ được đặt thành một. Mỗi lần một chuỗi lặp lại mutex này, số lượng khóa sẽ được tăng thêm một. Mỗi lần chuỗi mở khóa mutex, số lượng khóa sẽ bị giảm đi một. Khi số lượng khóa đạt đến số không, mutex sẽ trở thành có sẵn cho các chủ đề khác để có được. Nếu một chuỗi cố gắng mở khóa một mutex mà nó không bị khóa hoặc một mutex được mở khóa, một lỗi sẽ được trả về.

Nếu loại mutex là PTHREAD_MUTEX_DEFAULT, cố gắng đệ quy khóa kết quả mutex trong hành vi không xác định. Cố gắng mở khóa mutex nếu nó không bị khóa bởi kết quả của chuỗi cuộc gọi trong hành vi không xác định. Cố gắng mở khóa mutex nếu nó không bị khóa trong hành vi không xác định.

Tôi thường thích sử dụng các biến thể PTHREAD_MUTEX_RECURSIVE, vì trong trường hợp này, mutex sẽ có sẵn khi đếm đến 0 và chuỗi gọi không còn có bất kỳ khóa nào trên mutex này nữa.

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