Như @sarnold chỉ ra, theo mặc định chủ đề của bạn không thể bị hủy bỏ với pthread_cancel()
mà không gọi bất kỳ chức năng mà là những điểm hủy ... nhưng điều này có thể được thay đổi bằng cách sử dụng pthread_setcanceltype()
để đặt loại hủy của chuỗi thành không đồng bộ thay vì trì hoãn. Để làm điều đó, bạn sẽ thêm một cái gì đó như pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
gần bắt đầu chức năng chuỗi của bạn, trước khi bạn bắt đầu vòng lặp. Sau đó, bạn có thể chấm dứt chuỗi bằng cách gọi pthread_cancel(th)
từ main()
.
Lưu ý, mặc dù, hủy chuỗi theo cách này (dù không đồng bộ hay không) sẽ không dọn sạch bất kỳ tài nguyên nào được phân bổ trong hàm chuỗi (như chú thích của Kevin trong nhận xét). Để làm được điều này sạch sẽ, bạn có thể:
- Đảm bảo rằng các thread không làm bất cứ điều gì nó cần để làm sạch trước khi xuất cảnh (ví dụ sử dụng
malloc()
phân bổ một bộ đệm)
- Đảm bảo rằng bạn có một số cách làm sạch sau khi chỉ ở nơi khác, sau khi thoát khỏi luồng
- Sử dụng
pthread_cleanup_push()
và pthread_cleanup_pop()
để thêm trình xử lý dọn dẹp để dọn sạch tài nguyên khi chuỗi bị hủy. Lưu ý rằng điều này vẫn còn nguy hiểm nếu loại hủy không đồng bộ, vì chuỗi có thể bị hủy giữa phân bổ tài nguyên và thêm trình xử lý dọn dẹp.
- Tránh sử dụng
pthread_cancel()
và yêu cầu kiểm tra một số điều kiện để xác định thời điểm kết thúc (sẽ được kiểm tra trong các vòng chạy dài). Kể từ khi chủ đề của bạn sau đó kiểm tra cho chấm dứt chính nó, nó có thể làm bất cứ điều gì làm sạch nó cần phải sau khi kiểm tra.
Một cách để thực hiện lựa chọn cuối cùng là sử dụng một mutex như một lá cờ, và thử nghiệm nó với pthread_mutex_trylock()
bọc trong một chức năng để sử dụng trong các bài kiểm tra vòng lặp:
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
/* Returns 1 (true) if the mutex is unlocked, which is the
* thread's signal to terminate.
*/
int needQuit(pthread_mutex_t *mtx)
{
switch(pthread_mutex_trylock(mtx)) {
case 0: /* if we got the lock, unlock and return 1 (true) */
pthread_mutex_unlock(mtx);
return 1;
case EBUSY: /* return 0 (false) if the mutex was locked */
return 0;
}
return 1;
}
/* Thread function, containing a loop that's infinite except that it checks for
* termination with needQuit()
*/
void *thread_do(void *arg)
{
pthread_mutex_t *mx = arg;
while(!needQuit(mx)) {}
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t th;
pthread_mutex_t mxq; /* mutex used as quit flag */
/* init and lock the mutex before creating the thread. As long as the
mutex stays locked, the thread should keep running. A pointer to the
mutex is passed as the argument to the thread function. */
pthread_mutex_init(&mxq,NULL);
pthread_mutex_lock(&mxq);
pthread_create(&th,NULL,thread_do,&mxq);
sleep(2);
/* unlock mxq to tell the thread to terminate, then join the thread */
pthread_mutex_unlock(&mxq);
pthread_join(th,NULL);
sleep(2);
return 0;
}
Nếu thread không phải là tách ra (nó thường không theo mặc định), bạn nên gọi pthread_join()
sau khi dừng chuỗi.Nếu thread được tách ra, bạn không cần phải tham gia nó, nhưng bạn sẽ không biết chính xác khi nào nó chấm dứt (hoặc thậm chí xấp xỉ, trừ khi bạn thêm một cách khác để chỉ ra lối ra của nó).
Hủy bỏ pthreads có nghĩa là các chủ đề không có cơ hội để làm sạch bất kỳ bộ nhớ nó được phân bổ. –
Ok tôi đã giải quyết vấn đề này bằng cách chỉ có 'keepalive = 1' toàn cục. Sau đó, tôi đã thay đổi 'while (1)' thành 'while (keepalive)'. Để giết các chủ đề bây giờ tôi chỉ cần thay đổi giá trị của biến keepalive 0 và thì đấy! – Pithikos