Unix下最普遍的線程包是POSIX標準的Pthreads。Pthreads使用的搶佔式線程管理策略,程序中的一個線程可能在任何時候被另一個線程中斷。所以,使用Pthreads開發的應用程序有些錯誤不太容易重現。
GDB線程相關命令彙總
1 info threads給出關於當前所有線程的信息
2 thread n改爲線程n,或者說是進入線程n的棧中進行觀察
3 break line_num thread n表示當線程n到達源碼行line_num時停止執行
4 break line_num thread n if expression上一命令增加條件斷點而已
加入懷疑線程之間有死鎖,可以用gdb進行調試定位。流程大致是:
· 用gdb啓動或者插入待調試程序
· 當程序掛起時候,通過按下Ctrl+C組合鍵中斷它;
· 這個時候用info threads查看所有線程都在幹嘛,然後找到自己的工作線程(注意排除main線程和pthreads的管理線程)
· 分別查看自己的工作線程在幹嘛,用bt(backtrace)查看對應的幀,記得用thread n切換進入對應線程的幀
· 關注像__pthread_wait_for_restart_signal()和lock等函數,如果有源碼的話,會比較方便地定位到具體的問題代碼位置
下面是一個簡單的例子。如果在worker線程裏面,上鎖和解鎖沒有匹配,則會發生死鎖
// finds the primes between 2 and n; uses the Sieve ofEratosthenes,
// deleting all multiples of 2, all multiples of 3, allmultiples of 5,
// etc.; not efficient, e.g. each thread should do deletingfor a whole
// block of values of base before going to nextbase for more
// usage: sieventhreads n
// where nthreads is the number of worker threads
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#define MAX_N 100000000
#define MAX_THREADS 100
// shared variables
int nthreads, //number of threads (not counting main())
n, // upper bound of range in which to findprimes
prime[MAX_N+1], // in the end,prime[i] = 1 if i prime, else 0
nextbase; // next sieve multiplier to be used
int work[MAX_THREADS]; // to measure how much work each thread does,
// in terms of number of sieve multipliers checked
// lock index for the shared variable nextbase
pthread_mutex_t nextbaselock = PTHREAD_MUTEX_INITIALIZER;
// ID structs for the threads
pthread_t id[MAX_THREADS];
// "crosses out" all multiples of k, from k*k on
void crossout(int k)
{ int i;
for (i = k; i*k<= n; i++) {
prime[i*k] = 0;
}
}
// worker thread routine
void *worker(int tn) // tn is the thread number (0,1,...)
{ int lim,base;
// no need to checkmultipliers bigger than sqrt(n)
lim = sqrt(n);
do {
// get next sievemultiplier, avoiding duplication across threads
pthread_mutex_lock(&nextbaselock);
base = nextbase +=2;
pthread_mutex_unlock(&nextbaselock);
if (base <=lim) {
work[tn]++; // log work done bythis thread
// don'tbother with crossing out if base is known to be
// composite
if(prime[base])
crossout(base);
}
else return;
} while (1);
}
main(int argc, char **argv)
{ int nprimes, // number of primes found
totwork, // number of base values checked
i;
void *p;
n = atoi(argv[1]);
nthreads =atoi(argv[2]);
for (i = 2; i <=n; i++)
prime[i] = 1;
crossout(2);
nextbase = 1;
// get threads started
for (i = 0; i <nthreads; i++) {
pthread_create(&id[i],NULL,(void *) worker,(void *) i);
}
// wait for all done
totwork = 0;
for (i = 0; i <nthreads; i++) {
pthread_join(id[i],&p);
printf(" %d
values of basedone
/n
",work[i]);
totwork +=work[i];
}
printf("
%d
total valuesof base done
/n
",totwork);
// report results
nprimes = 0;
for (i = 2; i <=n; i++)
if (prime[i]) nprimes++;
printf("thenumber of primes found was %d
/n
",nprimes);
}