1. 程式人生 > >Linux多執行緒程式設計例項解析

Linux多執行緒程式設計例項解析

Linux系統下的多執行緒遵循POSIX執行緒介面,稱為 pthread。編寫Linux下的多執行緒程式,需要使用標頭檔案pthread.h,連線時需要使用庫libpthread.a。順便說一下,Linux 下pthread的實現是通過系統呼叫clone()來實現的。clone()是 Linux所特有的系統呼叫,它的使用方式類似fork,關於clone()的詳細情況,有興趣的讀者可以去檢視有關文件說明。下面我們展示一個最簡單的 多執行緒程式 pthread_create.c。


一個重要的執行緒建立函式原型:
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp,const pthread_attr_t *restrict attr, void *(*start_rtn)(void),void *restrict arg);

返回值:若是成功建立執行緒返回0,否則返回錯誤的編號
形式引數:
                pthread_t *restrict tidp 要建立的執行緒的執行緒id指標
                const pthread_attr_t *restrict attr 建立執行緒時的執行緒屬性
                void* (start_rtn)(void) 返回值是void型別的指標函式
                void *restrict arg   start_rtn的行參
                
例程1:                               
    功能:建立一個簡單的執行緒

    程式名稱:pthread_create.c   

程式碼如下:

#include <stdio.h>
#include <pthread.h>

void *mythread1(void)
{
	int i;
	for(i = 0; i < 10; i++)
	{
		printf("This is the 1st pthread,created by xiaoqiang!\n");
		sleep(1);
	}
}

void *mythread2(void)
{
	int i;
	for(i = 0; i < 10; i++)
	{
		printf("This is the 2st pthread,created by xiaoqiang!\n");
		sleep(1);
	}
}

int main(int argc, const char *argv[])
{
	int i = 0;
	int ret = 0;
	pthread_t id1,id2;

	ret = pthread_create(&id1, NULL, (void *)mythread1,NULL);
	if(ret)
	{
		printf("Create pthread error!\n");
		return 1;
	}

	ret = pthread_create(&id2, NULL, (void *)mythread2,NULL);
	if(ret)
	{
		printf("Create pthread error!\n");
		return 1;
	}
	
	pthread_join(id1,NULL);
	pthread_join(id2,NULL);

	return 0;
}

執行結果如下:

[email protected]:~/qiang/thread$ vi thread1.c
[email protected]:~/qiang/thread$ gcc -o thread1 thread1.c -lpthread
[email protected]:~/qiang/thread$ ./thread1
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 2st pthread,created by xiaoqiang!
This is the 1st pthread,created by xiaoqiang!
[email protected]
:~/qiang/thread$

兩個執行緒交替執行。
另外,因為pthread的庫不是linux系統的庫,所以在進行編譯的時候要加上-lpthread,否則編譯不過,會出現下面錯誤
thread_test.c: 在函式 ‘create’ 中:
thread_test.c:7: 警告: 在有返回值的函式中,程式流程到達函式尾
/tmp/ccOBJmuD.o: In function `main':thread_test.c:(.text+0x4f):對‘pthread_create’未定義的引用
collect2: ld 返回 1
此例子介紹了建立執行緒的方法

下面例子介紹向執行緒傳遞引數。
例程2:
功能:向新的執行緒傳遞整形值
程式名稱:pthread_int.c

程式碼如下:

#include <stdio.h>
#include <pthread.h>

void *create(void *arg)
{
	int *num;
	num = (int *)arg;
	printf("Create parameter is %d\n",*num);
	return (void *)0;
}

int main(int argc, const char *argv[])
{
	pthread_t id1;
	int error;

	int test = 4;
	int *attr = &test;

	error = pthread_create(&id1,NULL,create,(void *)attr);

	if(error)
	{
		printf("Pthread_create is not created!\n");
		return -1;
	}
	sleep(1);

	printf("Pthread_create is created..\n");
	return 0;
}

執行結果如下:

[email protected]:~/qiang/thread$ vi thread2.c
[email protected]:~/qiang/thread$ gcc -o thread2 thread2.c -lpthread
[email protected]:~/qiang/thread$ ./thread2
Create parameter is 4
Pthread_create is created..
[email protected]:~/qiang/thread$ 

例程總結:
    可以看出來,我們在main函式中傳遞的整行指標,傳遞到我們新建的執行緒函式中。

在上面的例子可以看出來我們向新的執行緒傳入了另一個執行緒的int資料,執行緒之間還可以傳遞字串或是更復雜的資料結構。
例程3:
程式功能:向新建的執行緒傳遞字串
程式名稱:pthread_string.c
程式碼如下:

#include <stdio.h>
#include <pthread.h>

void *create(char *arg)
{
	char *str;
	str = arg;
	printf("The parameter passed from main is %s\n",str);

	return (void *)0;
}

int main()
{
	int error;
	pthread_t id1;
	char *str1 = "Hello ,xiaoqiang!";
	char *attr = str1;
	error = pthread_create(&id1, NULL, create, (void *)attr);

	if(error != 0)
	{
		printf("This pthread is not created!\n");
		return -1;
	}
	sleep(1);

	printf("pthread is created..\n");
	return 0;
}

執行結果如下:

[email protected]:~/qiang/thread$ ./thread3
The parameter passed from main is Hello ,xiaoqiang!
pthread is created..
[email protected]:~/qiang/thread$ 

例程總結:
可以看出來main函式中的字串傳入了新建的執行緒中。

例程4:
程式功能:向新建的執行緒傳遞字串
程式名稱:pthread_struct.c

程式碼如下:

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

struct menber
{
	int a;
	char *s;
};

void *create(void *arg)
{
	struct menber *temp;
	temp = (struct menber *)arg;
	printf("menber->a = %d\n",temp->a);
	printf("menber->s = %s\n",temp->s);

	return (void *)0;
}

int main()
{
	int error;
	pthread_t id1;
	struct menber *p;
	p = (struct menber *)malloc(sizeof(struct menber));
	p->a = 1;
	p->s = "xiaoqiang!";

	error = pthread_create(&id1,NULL,create,(void *)p);

	if(error)
	{
		printf("pthread is not created!\n");
		return -1;
	}
	sleep(1);
	printf("pthread is created!\n");

	free(p);
	p = NULL;
	return 0;
}

執行結果如下:

[email protected]:~/qiang/thread$ vi thread4.c
[email protected]:~/qiang/thread$ gcc -o thread4 thread4.c -lpthread
[email protected]:~/qiang/thread$ ./thread4
menber->a = 1
menber->s = xiaoqiang!
pthread is created!
[email protected]:~/qiang/thread$ 

例程總結:
    可以看出來main函式中的一個結構體傳入了新建的執行緒中。
    執行緒包含了標識程序內執行環境必須的資訊。他集成了程序中的所有資訊都是對執行緒進行共享的,包括文字程式、程式的全域性記憶體和堆記憶體、棧以及檔案描述符

例程5:
程式目的:驗證新建立的執行緒可以共享程序中的資料
程式名稱:pthread_share.c

程式碼如下:

#include <stdio.h>
#include <pthread.h>

static int a = 5;

void *create(void *arg)
{
	printf("New pthread...\n");
	printf("a = %d\n",a);

	return (void *)0;
}

int main(int argc, const char *argv[])
{
	int error;
	pthread_t id1;

	error = pthread_create(&id1, NULL, create, NULL);
	if(error != 0)
	{
		printf("new thread is not created!\n");
		return -1;
	}
	sleep(1);
	printf("New thread is created...\n");

	return 0;
}

結果如下:

[email protected]:~/qiang/thread$ vi thread5.c
[email protected]:~/qiang/thread$ gcc -o thread5 thread5.c -lpthread
[email protected]:~/qiang/thread$ ./thread5
New pthread...
a = 5
New thread is created...
[email protected]:~/qiang/thread$ 

例程總結:
可以看出來,我們在主執行緒更改了我們的全域性變數a的值的時候,我們新建立的執行緒則打印出來了改變的值,可以看出可以訪問執行緒所在程序中的資料資訊。

2、執行緒的終止
如果程序中任何一個執行緒中呼叫exit,_Exit,或者是_exit,那麼整個程序就會終止,
與此類似,如果訊號的預設的動作是終止程序,那麼,把該訊號傳送到執行緒會終止程序。
執行緒的正常退出的方式:
(1) 執行緒只是從啟動例程中返回,返回值是執行緒中的退出碼
(2) 執行緒可以被另一個程序進行終止
(3) 執行緒自己呼叫pthread_exit函式

兩個重要的函式原型:

include <pthread.h>
void pthread_exit(void *rval_ptr);
/*rval_ptr 執行緒退出返回的指標*/

int pthread_join(pthread_t thread,void **rval_ptr);
   /*成功結束程序為0,否則為錯誤編碼*/

pthread_join使一個執行緒等待另一個執行緒結束。 程式碼中如果沒有pthread_join主執行緒會很快結束從而使整個程序結束,從而使建立的執行緒沒有機會開始執行就結束了。加入pthread_join後,主執行緒會一直等待直到等待的執行緒結束自己才結束,使建立的執行緒有機會執行。 標頭檔案 : #include <pthread.h> 函式定義: int pthread_join(pthread_t thread, void **retval); 描述 :pthread_join()函式,以阻塞的方式等待thread指定的執行緒結束。當函式返回時,被等待執行緒的資源被收回。如果執行緒已經結束,那麼該函式會立即返回。並且thread指定的執行緒必須是joinable的。 引數 :thread: 執行緒識別符號,即執行緒ID,標識唯一執行緒。retval: 使用者定義的指標,用來儲存被等待執行緒的返回值。 返回值 : 0代表成功。 失敗,返回的則是錯誤號。

例程6
程式目的:執行緒正常退出,接受執行緒退出的返回碼
程式名稱:pthread_exit.c
執行程式碼如下:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *create(void *arg)
{
	printf("new thread is created ... \n");
	return (void *)0;
}

int main(int argc,char *argv[])
{
	pthread_t tid;
	int error;
	void *temp;

	error = pthread_create(&tid, NULL, create, NULL);

	if( error )
	{
		printf("thread is not created ... \n");
		return -1;
	}
	error = pthread_join(tid, &temp);

	if( error )
	{
		printf("thread is not exit ... \n");
		return -2;
	}

	printf("thread is exit code %d \n", (int )temp);
									    
	return 0;
}

執行結果如下:

[email protected]:~/qiang/thread$ vi thread6.c
[email protected]:~/qiang/thread$ gcc -o thread6 thread6.c -lpthread
[email protected]:~/qiang/thread$ ./thread6
new thread is created ... 
thread is exit code 0 
[email protected]:~/qiang/thread$ 

例程總結:
可以看出來,執行緒退出可以返回執行緒的int數值。

執行緒退出不僅僅可以返回執行緒的int數值,還可以返回一個複雜的資料結構

例程7
程式目的:執行緒結束返回一個複雜的資料結構
程式碼如下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct menber
{
	int a;
	char *b;
}temp={8,"xiaoqiang"};

void *create(void *arg)
{
	printf("new thread ... \n");
	return (void *)&temp;
}

int main(int argc,char *argv[])
{
	int error;
	pthread_t tid;
	struct menber *c;

	error = pthread_create(&tid, NULL, create, NULL);

	if( error )
	{
		printf("new thread is not created ... \n");
		return -1;
	}
	printf("main ... \n");

	error = pthread_join(tid,(void *)&c);

	if( error )
	{
		printf("new thread is not exit ... \n");
		return -2;
	}
	printf("c->a = %d  \n",c->a);
	printf("c->b = %s  \n",c->b);
	sleep(1);
	return 0;
}
執行結果如下:
[email protected]:~/qiang/thread$ gcc -o thread7 thread7.c -lpthread
[email protected]:~/qiang/thread$ ./thread7
main ... 
new thread ... 
c->a = 8  
c->b = xiaoqiang  
[email protected]:~/qiang/thread$ 
例程總結:
一定要記得返回的資料結構要是在這個資料要返回的結構沒有釋放的時候應用,如果資料結構已經發生變化,那返回的就不會是我們所需要的,而是髒資料。 3、執行緒標識
      函式原型: #include <pthread.h>
pthread_t pthread_self(void);
pid_t getpid(void);
    getpid()用來取得目前程序的程序識別碼,函式說明

例程8
程式目的:實現在新建立的執行緒中列印該執行緒的id和程序id
程式碼如下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> /*getpid()*/

void *create(void *arg)
{
	printf("New thread .... \n");
	printf("This thread's id is %u  \n", (unsigned int)pthread_self());
	printf("The process pid is %d  \n",getpid());
	return (void *)0;
}

int main(int argc,char *argv[])
{
	pthread_t tid;
	int error;

	printf("Main thread is starting ... \n");

	error = pthread_create(&tid, NULL, create, NULL);

	if(error)
	{
		printf("thread is not created ... \n");
		return -1;
	}
	printf("The main process's pid is %d  \n",getpid());
	sleep(1);
	return 0;
}
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
執行結果如下:
[email protected]:~/qiang/thread$ gcc -o thread8 thread8.c -lpthread
[email protected]:~/qiang/thread$ ./thread8
Main thread is starting ... 
The main process's pid is 4955  
New thread .... 
This thread's id is 3075853120  
The process pid is 4955  
[email protected]:~/qiang/thread$ 




相關推薦

Linux執行程式設計例項解析

Linux系統下的多執行緒遵循POSIX執行緒介面,稱為 pthread。編寫Linux下的多執行緒程式,需要使用標頭檔案pthread.h,連線時需要使用庫libpthread.a。順便說一下,Linux 下pthread的實現是通過系統呼叫clone()來實現的。clo

Linux執行程式設計詳細解析----條件變數 pthread_cond_t

Linux作業系統下的多執行緒程式設計詳細解析----條件變數 1.初始化條件變數pthread_cond_init #include <pthread.h> int pthread_cond_init(pthread_cond_t *cv, const pth

Linux作業系統下的執行程式設計詳細解析----條件變數pthread_cond_t

在多執行緒程式設計下,常常出現A執行緒要等待B執行緒條件完成後再繼續進行,這裡等待方式有兩種: 1.使用鎖+輪詢        使用這種方法可以很簡單的實現,但是會有一定的效能消耗,其還有一個點要好好把握,就是一次輪詢沒有結果後相隔多久進行下一次的輪詢,間隔時間太短,消耗

linux環境下ssl執行程式設計例項(整理)

服務端: #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <errno.h> #ifndef    _WIN32 #include <

Linux執行程式設計---執行間同步(互斥鎖、條件變數、訊號量和讀寫鎖)

本篇博文轉自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了多種方式來處理執行緒同步,最常用的是互斥鎖、條件變數、訊號量和讀寫鎖。  下面是思維導

Java執行程式設計詳細解析

Java多執行緒程式設計詳細解析   一、理解多執行緒多執行緒是這樣一種機制,它允許在程式中併發執行多個指令流,每個指令流都稱為一個執行緒,彼此間互相獨立。執行緒又稱為輕量級程序,它和程序一樣擁有獨立的執行控制,由作業系統負責排程,區別在於執行緒沒有獨立的儲存空間,而是和所屬程

java基礎總結(三十二)--java執行程式設計例項

來自:https://blog.csdn.net/qq_34996727/article/details/80416277或者https://www.cnblogs.com/pureEve/p/6524366.html 一.相關知識:   Java多執行緒程式設計到的知識:

linux執行程式設計,用 pthread_cond_timedwait 代替sleep

摘要:多執行緒程式設計中,執行緒A迴圈計算,然後sleep一會接著計算(目的是減少CPU利用率);存在的問題是,如果要關閉程式,通常選擇join執行緒A等待執行緒A退出,可是我們必須等到sleep函式返回,該執行緒A才能正常退出,這無疑減慢了程式退出的速度。當然,你可以terminate執行緒A,但

Linux執行程式設計

執行緒概念     執行緒是指執行中的程式的排程單位。一個執行緒指的是程序中一個單一順序的控制流,也被稱為輕量級執行緒。它是系統獨立排程和分配的基本單位。同一程序中的多個執行緒將共享該系統中的全部系統資源,比如檔案描述符和訊號處理等。一個程序可以有很多執行緒,每

Linux執行程式設計入門

1 執行緒基本知識 程序是資源管理的基本單元,而執行緒是系統排程的基本單元,執行緒是作業系統能夠進行排程運算的最小單位,它被包含在程序之中,是程序中的實際運作單位。一條執行緒指的是程序中一個單一順序的控制流,一個程序中可以併發多個執行緒,每條執行緒並行執行不同

Linux執行程式設計小結

 Linux多執行緒程式設計小結 前一段時間因為開題的事情一直耽擱了我搞Linux的進度,搞的我之前學的東西都遺忘了,很煩躁的說,現在抽個時間把之前所學的做個小節。文章內容主要總結於《Linux程式設計第3版》。 1.Linux程序與執行緒 Linux程序建立一個新執行緒時

Linux 執行程式設計(一)

Linux 多執行緒程式設計 執行緒(Thread)已被許多作業系統所支援,包括Windows/NT ,Linux 以前的多執行緒其實是多程序,而現在意味著一個程序中有多個執行緒 使用多執行緒的原因(多執行緒的優點): 1.“節省”,啟動一個新的程序需要分配給它獨立的地

Linux執行程式設計之員工資訊管理系統

       員工資訊管理系統是基於Linux 多執行緒併發伺服器程式設計,由伺服器端和客戶端構成,客戶端可以執行在多個不同的主機上連線伺服器,伺服器對員工資訊的操作結果通過“員工資訊檔案”來儲存,即:“員工資訊”存放在後臺的檔案中,相當於資料庫。當用戶登入後,根據使用者名稱

linux執行程式設計,你還在用sleep麼?用pthread_cond_timedwait吧

摘要:多執行緒程式設計中,執行緒A迴圈計算,然後sleep一會接著計算(目的是減少CPU利用率);存在的問題是,如果要關閉程式,通常選擇join執行緒A等待執行緒A退出,可是我們必須等到sleep函式返回,該執行緒A才能正常退出,這無疑減慢了程式退出的速度。當然,你可以terminate執行緒A,但這樣做

Linux執行同步機制 .linux執行程式設計機制

#include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_mutex_t mutex; pthread_cond_t  cond; void * child1(void *arg) {      

Linux執行程式設計(不限Linux))執行操作

——本文一個例子展開,介紹Linux下面執行緒的操作、多執行緒的同步和互斥。 前言 執行緒?為什麼有了程序還需要執行緒呢,他們有什麼區別?使用執行緒有什麼優勢呢?還有多執行緒程式設計的一些細節問題,如執行緒之間怎樣同步、互斥,這些東西將在本文中介紹。我在某QQ群裡見到這樣一道面試題: 是否熟悉POS

Linux執行程式設計講解之系列六

執行緒安全介紹 在目前的電腦科學中,執行緒是作業系統排程的最小單元,程序是資源分配的最小單元。在大多數作業系統中,一個程序可以同時派生出多個執行緒。這些執行緒獨立執行,共享程序的資源。在單處理器系統中,多執行緒通過分時複用技術來技術,處理器在不同的執行緒間切換,從而更高效地利用系統 CPU資源。

Linux執行程式設計講解之系列五

在Posix執行緒規範中還有幾個輔助函式難以歸類,暫且稱其為雜項函式,主要包括pthread_self()、pthread_equal()和pthread_once()三個,另外還有一個LinuxThreads非可移植性擴充套件函式pthread_kill_other_t

linux執行程式設計(C):訊號量實現的執行安全佇列

用訊號量實現的執行緒安全佇列。 簡單有用的示例程式, 比起互斥量的實現在多執行緒時效率更好。 cir_queue.h /* * \File * cir_queue.h * \Brief * circular queue */#ifndef __CIR_QUEUE_H_

Linux執行程式設計———重點區分

多執行緒 執行緒(thread)技術早在60年代就被提出,但真正應用多執行緒到作業系統中去,是在80年代中期,solaris是這方面的佼佼者.傳統的Unix也支援執行緒的概念,但是在一個程序(process)中只允許有一個執行緒,這樣多執行緒就意味著多程序.現