實驗目的:
通過實驗掌握下列知識:
1、在Linux環境下,掌握pthread庫中的mutex對象,pthread_mutex_lock()函數,pthread_mutex_init和pthread_self()的用法。
2、在Linux環境下,掌握pthread_create()函數,pthread_join()函數的用法。
3、在Linux環境下,掌握pthread_cancel(pthread_t
thread),pthread_kill()的用法。
一、多線程和互斥鎖
(1) 使用頭檔案,pthread_mutex_lock()函數鎖住由mutex指定的mutex
對象。如果mutex已經被鎖住,調用pthread_mutex_lock()函數的線程阻塞直到mutex可用為止。pthread_self()可以獲得線程自身的ID。pthread_mutex_init用于互斥鎖的初始化。
#include
#include
#include
int data=0;
//共享資料
pthread_mutex_t mutex;
//互斥鎖
void *thread1(void
*argu)
//子線程執行函數
{
int
i;
if(pthread_mutex_lock(&mutex)!=0)
{
printf("lock error!\n");
return NULL;
}
for(i=0;i<6;i++)
{
printf("thread2: %d =
%d\n",pthread_self(),data++);
sleep(1);
}
if(pthread_mutex_unlock(&mutex)!=0)
{
printf("unlock error!\n");
return NULL;
}
}
int main()
{
pthread_t id;
int
i;
if(pthread_mutex_init(&mutex,NULL)!=0)
//在建立線程之前初始化鎖
{
printf("init error!\n");
return 1;
}
int
ret=pthread_create(&id,NULL,thread1,NULL);
//建立子線程
if(ret!=0)
{
printf("creata error!\n");
return 1;
}
if(pthread_mutex_lock(&mutex)!=0)
//對共享資料加鎖
{
printf("lock error!\n");
return 1;
}
for(i=0;i<6;i++)
{
printf("thread1: %d %d ",pthread_self(),data++);
sleep(1);
}
if(pthread_mutex_unlock(&mutex)!=0)
//對共享資料解鎖
{
printf("unlock error!\n");
return 1;
}
pthread_join(id,NULL);
return 0;
}
完成程式的編寫,輸入以下指令,對pthread1.c程式進行編譯,在編譯時,需要添加pthread的庫檔案。
$ gcc pthread1.c -o pthread1
–lpthread
二、多線程的建立
(2)線程的建立,利用線程調用函數。
#include
#include
#include
#include
#include
pthread_t
ntid;
void printids(const
char *s)
{
pid_t pid;
pthread_t
tid;
pid =
getpid();//傳回目前的程序号
tid =
pthread_self();
//傳回目前線程的線程ID号
printf("%s pid %u tid %u
(0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned
int)tid);
}
void *thr_fn(void
*arg)
{
printids(arg); return
NULL;
}
int
main(void)
{
int err;
err =
pthread_create(&ntid, NULL, thr_fn, "new thread:
"); //建立程序,并傳遞”new
thread”參數
if (err !=
0)
{
fprintf(stderr, "can't create
thread: %s\n", strerror(err));
exit(1);
}
printids("main
thread:");
//再次調用printids函數
sleep(1);
return 0;
}
完成程式的編寫,輸入以下指令,對thread2.c程式進行編譯,在編譯時,需要添加pthread的庫檔案。
$ gcc thread2.c -o thread2
-lpthread
./thread2
main thread: pid 7398 tid
3084450496 (0xb7d8fac0)
new thread: pid 7398 tid
3084446608 (0xb7d8eb90)
(3)定理三個函數線程,利用pthread_create ()中四個參數分别是:第一個參數為指向線程辨別符的指針;第二個參數用來設定線程屬性;第三個參數是線程運作函數的起始位址;
最後一個參數是運作函數的參數。pthread_join等待線程結束,第一個參數thread: 線程辨別符,即線程ID,辨別唯一線程;第二個參數用來設定使用者定義的指針,用來存儲被等待線程的傳回值。retval傳回值:0代表成功。失敗,傳回的則是錯誤号。
#include
#include
#include
#include
void *thr_fn1(void
*arg)
{
printf("thread 1
returning\n");
return (void
*)1;
}
void *thr_fn2(void
*arg)
{
printf("thread 2
exiting\n");
pthread_exit((void
*)2);
//調用pthread_exit函數終止執行
}
void *thr_fn3(void
*arg)
{
while(1) {
printf("thread 3
writing\n");
sleep(1);
}
}
int
main(void)
{
pthread_t
tid;
void *tret;
pthread_create(&tid, NULL,
thr_fn1, NULL);
//建立線程tid,調用thr_fn1函數
pthread_join(tid,
&tret);
//等待線程tid結束
printf("thread 1 exit code
%d\n", (int)tret);
//列印線程tid的傳回值
pthread_create(&tid, NULL,
thr_fn2, NULL);
//建立線程tid,調用thr_fn2函數
pthread_join(tid,
&tret);
//等待線程tid結束
printf("thread 2 exit code
%d\n", (int)tret);
//列印線程tid的傳回值
pthread_create(&tid, NULL,
thr_fn3, NULL);
//建立線程tid,調用thr_fn3函數
sleep(3);
//休眠3秒
pthread_cancel(tid);
//發送終止信号給thread線程
pthread_join(tid,
&tret);
//等待線程tid結束
printf("thread 3 exit code
%d\n", (int)tret);
return 0;
}
完成程式的編寫,輸入以下指令,對thread3.c程式進行編譯,在編譯時,需要添加pthread的庫檔案。
$ gcc thread3.c -o thread3
-lpthread
./thread3