Chỉ cần bạn biết điều gì đang xảy ra, "vòng lặp chặt chẽ" tiêu thụ phân bổ CPU của chủ đề giống như bất kỳ mã nào khác mà chuỗi của bạn thực hiện. Sự khác biệt duy nhất là nó hoàn thành không có gì. Vâng, tôi đoán làm cho lõi ấm là thứ gì đó ... Bạn có thể không bao giờ muốn làm điều đó trừ khi bạn quan tâm đến chi phí chuyển ngữ cảnh và bạn biết cho chắc chắn rằng thời gian chờ sẽ ngắn hơn nhiều so với thời gian của chuỗi của bạn , khoảng 1ms. Tôi không biết liệu giấc ngủ có tệ như năng suất hay không (AFAIK yield thiết lập luồng của bạn ở mặt sau của danh sách các chuỗi để kích hoạt ở mức ưu tiên của bạn), nhưng cả hai ít nhất phải chịu hình phạt của một chuyển ngữ cảnh. Có một chi phí để chuyển đổi ngữ cảnh. Chuyển đổi ngữ cảnh là điều sẽ xảy ra khi thời gian của chuỗi của bạn kết thúc. Nó có thể kết thúc bởi vì bạn đã kết thúc nó với một sản lượng hoặc một giấc ngủ, hoặc nếu hạt nhân đã kết thúc nó bằng cách làm trống trước bạn. Đọc về SMP và spinlocks để hiểu thêm về các chuyển mạch bối cảnh và các trường hợp khi có vòng lặp chặt chẽ.
Ngoài ra, khi bạn ngủ, bạn không biết chính xác khi nào bạn sẽ thức dậy lần nữa. vì vậy một trong những lý do bạn có thể không muốn ngủ là bạn cần phải làm một cái gì đó được thực hiện nhanh chóng.Bạn có thể đợi một vài ms trước khi được lên lịch lại.
Mọi người khác đã cung cấp cho bạn giải pháp pthread_cond_wait, yêu cầu khóa thông qua mutexes và trông đơn giản và đơn giản. Hiệu suất có thể phù hợp với nhu cầu của bạn, nhưng tương đối chậm so với tín hiệu sử dụng giải pháp (sigwait and pthread_kill). Sự phức tạp sẽ lẻn vào bạn.
Không được thảo luận ở đây là lý do tại sao bạn khóa một mutex trước khi thử nghiệm nếu bạn cần phải chờ điều kiện. Lý do là mã như thế này có một lỗ hổng:
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
chủ đề của bạn có thể kiểm tra (X < = Y), thấy rằng nó phải chờ đợi, nhưng được pre-epted trước khi nó tự gắn nó với giá trị điều kiện. Một số chủ đề khác, người vừa sửa đổi x hoặc y, báo hiệu điều kiện trong khoảng thời gian đó trước khi chuỗi đầu tiên gắn với điều kiện. Bằng cách này, tín hiệu điều kiện bị mất. Vì vậy, những gì kết thúc xảy ra là ở khắp mọi nơi bạn sửa đổi các biến lây nhiễm tín hiệu, bạn phải thêm khóa.
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
Điều này có nghĩa là bạn thêm các khóa mutex này ở nhiều nơi khác nhau và mã của bạn trở nên phức tạp và chậm hơn do đó. Khả năng của một chủ đề treo chờ đợi một điều kiện luôn ở đó. Vòng lặp, kiểm tra, giải pháp ngủ không có vấn đề nào trong số đó. Vì vậy, nếu thời gian chờ đợi được gọi là ngắn, sử dụng giấc ngủ trong một vòng lặp có lẽ là một giải pháp tốt. Đặc biệt là nếu bạn có thể ngủ trong một giây hoặc lâu hơn giữa các lần kiểm tra. Nếu bạn có thể, sau đó không bận tâm với mutexes và điều kiện. Nếu thời gian ngủ ngắn, như 1ms và thời gian chờ là dài, như phút hoặc giờ, thì bạn sẽ kết thúc lãng phí một số tài nguyên bằng cách liên tục thức dậy và trở lại trạng thái ngủ. Bạn phải phán xét.
Cũng cần lưu ý rằng đôi khi hạt nhân sẽ cố gắng đánh thức chuỗi người phục vụ ngay lập tức và các thời điểm khác sẽ có sự chậm trễ. Nếu thread đánh thức quá sớm, nó sẽ đánh thức trong khi mutex bị khóa và ngay lập tức quay trở lại trạng thái ngủ cho đến khi mutex mở khóa. Nếu điều đó trở thành sự cố, hãy báo hiệu điều kiện theo cách này:
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) {
pthread_mutex_unlock(&mut);
pthread_cond_broadcast(&cond);
} else
pthread_mutex_unlock(&mut);
Cảm ơn người dùng576875, mẫu mã tôi đã sao chép.
Lưu ý rằng bạn phải lặp với vòng lặp 'while()' như được hiển thị trong các ví dụ, vì bạn có thể bị đánh thức với điều kiện không đúng. – caf