2011-01-25 33 views
8

Tôi đang mã hóa trong C (thực tế trong OOC sau đó được biên dịch thành C).Làm thế nào để dừng lại và tiếp tục một pthread?

Làm cách nào để hướng dẫn một chuỗi đợi tại một trạm kiểm soát cụ thể cho đến khi một số luồng khác yêu cầu nó tiếp tục?

Tôi thực sự đang sử dụng vòng lặp chặt trong chuỗi và bỏ phiếu cho một biến tôi đang thay đổi từ chuỗi chính, nhưng tôi nghĩ điều đó không hoạt động tốt, đúng không? Bên cạnh đó, khi tôi làm một vòng lặp chặt chẽ trong một sợi, tôi nên bao gồm một giấc ngủ trong vòng lặp để tránh tiêu thụ nhiều cpu điện chỉ looping?

Trả lời

10

Có vẻ như bạn đang tìm kiếm pthread_cond_wait và chức năng liên quan của nó.

Dưới đây là một trích dẫn từ manpage với một ví dụ:

Hãy xem xét hai chia sẻ các biến x và y, bảo vệ bởi mứt mutex, và một biến điều kiện cond mà là để được báo hiệu mỗi khi x trở nên lớn hơn y.

  int x,y; 
      pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 
      pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 

Chờ đợi cho đến khi x lớn hơn y được thực hiện như sau:

  pthread_mutex_lock(&mut); 
      while (x <= y) { 
        pthread_cond_wait(&cond, &mut); 
      } 
      /* operate on x and y */ 
      pthread_mutex_unlock(&mut); 

Modifications vào x và y có khả năng gây x để trở thành lớn hơn y nên tín hiệu điều kiện nếu cần thiết:

  pthread_mutex_lock(&mut); 
      /* modify x and y */ 
      if (x > y) pthread_cond_broadcast(&cond); 
      pthread_mutex_unlock(&mut); 

Cuối cùng nó thực hiện những gì bạn đang yêu cầu: chủ đề gọi pthread_cond_wait(&cond) bị chặn cho đến khi một số khác quảng cáo (ví dụ chính của bạn) gọi pthread_cond_broadcast(&cond). Trong thời gian này nó chỉ ở trạng thái blocked và không tiêu thụ chu kỳ CPU.

+0

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

2

Tôi nghĩ đó là một ứng cử viên tốt cho một điều kiện. Các chủ đề nên chờ đợi trên một điều kiện và thread khác nên báo hiệu điều kiện để cho thread này tiếp tục.

bạn có thể tra cứu pthread_cond_init và đó sẽ dẫn đến các chức năng khác

2

Bạn nên xem xét các nguyên tắc đồng bộ hóa thích hợp như mutexes, biến điều kiện và semaphores. Trong trường hợp này, có vẻ như condition variable là công cụ thích hợp nhất từ ​​thư viện pthreads.

1

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.

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