日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux中多线程解析

發布時間:2024/1/17 linux 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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??????
/********************************************************************************************
**??? Name:pthread_create.c
**??? Used to study the multithread programming in Linux OS
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *myThread1(void)
{
??? int i;
??? for (i=0; i<100; i++)
??? {
??????? printf("This is the 1st pthread,created by zieckey./n");
??????? sleep(1);//Let this thread to sleep 1 second,and then continue to run
??? }
}

void *myThread2(void)
{
??? int i;
??? for (i=0; i<100; i++)
??? {
??????? printf("This is the 2st pthread,created by zieckey./n");
??????? sleep(1);
??? }
}

int main()
{
??? int i=0, ret=0;
??? pthread_t id1,id2;
? ?
??? ret = pthread_create(&id2, 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;
}


我們編譯此程序:
# gcc pthread_create.c -lpthread

因為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

運行,我們得到如下結果:
# ./a.out
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 2st pthread,created by zieckey.
This is the 1st pthread,created by zieckey.
....

兩個線程交替執行。
此例子介紹了創建線程的方法。
下面例子介紹向線程傳遞參數。


例程2:
??? 功能:向新的線程傳遞整形值
??? 程序名稱:pthread_int.c
/********************************************************************************************
**??? Name:pthread_int.c
**??? Used to study the multithread programming in Linux OS
**??? Pass a parameter to the thread.
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *create(void *arg)
{
??? int *num;
??? num=(int *)arg;
??? printf("create parameter is %d /n",*num);
??? return (void *)0;
}
int main(int argc ,char *argv[])
{
??? pthread_t tidp;
??? int error;
? ?
??? int test=4;
??? int *attr=&test;
? ?
??? error=pthread_create(&tidp,NULL,create,(void *)attr);

??? if(error)
??????? {
??????? printf("pthread_create is created is not created ... /n");
??????? return -1;
??????? }
??? sleep(1);
??? printf("pthread_create is created .../n");
??? return 0;????? ?
}


??? 編譯方法:

gcc -lpthread pthread_int.c -Wall


??? 執行結果:

create parameter is 4
pthread_create is created is? created ...


??? 例程總結:
??? 可以看出來,我們在main函數中傳遞的整行指針,傳遞到我們新建的線程函數中。
??? 在上面的例子可以看出來我們向新的線程傳入了另一個線程的int數據,線程之間還可以傳遞字符串或是更復雜的數據結構。

例程3:
??? 程序功能:向新建的線程傳遞字符串
??????? 程序名稱:pthread_string.c
/********************************************************************************************
**??? Name:pthread_string.c
**??? Used to study the multithread programming in Linux OS
**??? Pass a ‘char*‘ parameter to the thread.
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void *create(void *arg)
{
??? char *name;
??? name=(char *)arg;
??? printf("The parameter passed from main function is %s? /n",name);
??? return (void *)0;
}

int main(int argc, char *argv[])
{
??? char *a="zieckey";
??? int error;
??? pthread_t tidp;

??? error=pthread_create(&tidp, NULL, create, (void *)a);

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

? 編譯方法:

gcc -Wall pthread_string.c -lpthread


??? 執行結果:
The parameter passed from main function is zieckey
pthread is created...


??? 例程總結:
??? 可以看出來main函數中的字符串傳入了新建的線程中。

例程4:
??? 程序功能:向新建的線程傳遞字符串
??????? 程序名稱:pthread_struct.c
/********************************************************************************************
**??? Name:pthread_struct.c
**??? Used to study the multithread programming in Linux OS
**??? Pass a ‘char*‘ parameter to the thread.
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.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 argc,char *argv[])
{
??? pthread_t tidp;
??? int error;
??? struct menber *b;
??? b=(struct menber *)malloc( sizeof(struct menber) );
??? b->a = 4;
??? b->s = "zieckey";

??? error = pthread_create(&tidp, NULL, create, (void *)b);

??? if( error )
??? {
??????? printf("phread is not created.../n");
??????? return -1;
??? }
??? sleep(1);
??? printf("pthread is created.../n");
??? return 0;
}

? 編譯方法:

gcc -Wall pthread_struct.c -lpthread


??? 執行結果:
menber->a = 4
menber->s = zieckey
pthread is created...

??? 例程總結:
??? 可以看出來main函數中的一個結構體傳入了新建的線程中。
??? 線程包含了標識進程內執行環境必須的信息。他集成了進程中的所有信息都是對線程進行共享的,包括文本程序、程序的全局內存和堆內存、棧以及文件描述符。
? ?

例程5:
??? 程序目的:驗證新建立的線程可以共享進程中的數據
??? 程序名稱:pthread_share.c

/********************************************************************************************
**??? Name:pthread_share_data.c
**??? Used to study the multithread programming in Linux OS
**??? Pass a ‘char*‘ parameter to the thread.
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

static int a=4;
void *create(void *arg)
{
??? printf("new pthread ... /n");
??? printf("a=%d? /n",a);
??? return (void *)0;
}

int main(int argc,char *argv[])
{
??? pthread_t tidp;
??? int error;
? ?
??? a=5;

??? error=pthread_create(&tidp, NULL, create, NULL);

??? if(error!=0)
??? {
??????? printf("new thread is not create ... /n");
??????? return -1;
??? }
? ?
??? sleep(1);
? ?
??? printf("new thread is created ... /n");
??? return 0;
}
? ?
? 編譯方法:

gcc -Wall pthread_share_data.c -lpthread


??? 執行結果:
new pthread ...
a=5
new thread is created ...


??? 例程總結:
可以看出來,我們在主線程更改了我們的全局變量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,否則為錯誤編碼*/


??? 例程6
??? 程序目的:線程正常退出,接受線程退出的返回碼
??? 程序名稱:pthread_exit.c

/********************************************************************************************
**??? Name:pthread_exit.c
**??? Used to study the multithread programming in Linux OS
**??? A example showing a thread to exit and with a return code.
**??? Author:zeickey
**??? Date:2006/9/16?????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/

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

void *create(void *arg)
{
??? printf("new thread is created ... /n");
??? return (void *)8;
}

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;
}

? 編譯方法:

gcc -Wall pthread_exit.c -lpthread


??? 執行結果:
new thread is created ...
thread is exit code 8

??? 例程總結:
可以看出來,線程退出可以返回線程的int數值。線程退出不僅僅可以返回線程的int數值,還可以返回一個復雜的數據結構。

??? 例程7
??? 程序目的:線程結束返回一個復雜的數據結構
??? 程序名稱:pthread_return_struct.c
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

struct menber
{
??? int a;
??? char *b;
}temp={8,"zieckey"};
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;
}


? 編譯方法:

gcc -Wall pthread_return_struct.c -lpthread


??? 執行結果:

main ...
new thread ...
c->a = 8
c->b = zieckey


例程總結:
一定要記得返回的數據結構要是在這個數據要返回的結構沒有釋放的時候應用,
如果數據結構已經發生變化,那返回的就不會是我們所需要的,而是臟數據
3、線程標識

??? 函數原型:
? ?
#include <pthread.h>
pthread_t pthread_self(void);

pid_t getpid(void);
??? getpid()用來取得目前進程的進程識別碼,函數說明

??? 例程8
??? 程序目的:實現在新建立的線程中打印該線程的id和進程id
??? 程序名稱:pthread_id.c
?
/********************************************************************************************
**??? Name:pthread_id.c
**??? Used to study the multithread programming in Linux OS.
**??? Showing how to get the thread's tid and the process's pid.
**??? Author:zeickey
**??? Date:2006/9/16????? ?
**??? Copyright (c) 2006,All Rights Reserved!
*********************************************************************************************/
#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;
}


??? 編譯方法:

?
gcc -Wall -lpthread pthread_id.c

??? 執行結果:

Main thread is starting ...
The main process's pid is 3307
New thread ....
This thread's id is 3086347152
The process pid is 3307

?

?

?

介紹linux線程的基本概念,線程間的互斥和同步機制,分析了linuxpthread庫的API函數,并結合一個例子闡述多線程編程的核心技術,最后總結出多線程編程應注意的事項。

關鍵詞 線程進程 同步 互斥 中圖分類號:TP316 文獻標識碼:A 1.引言 目前,許多流行的多任務操作系統都提供線程機制,線程就是程序中的單個順序控制流。利用多線程進行程序設計,就是將一個程序(進程)的任務劃分為執行的多個部分(線程) ,每一個線程為一個順序的單控制流,而所有線程都是并發執行的,這樣,多線程程序就可以實現并行計算,高效利用多處理器。線程可分為用戶級線程和內核級線程兩種基本類型。用戶級線程不需要內核支持,可以在用戶程序中實現,線程調度、同步與互斥都需要用戶程序自己完成。內核級線程需要內核參與,由內核完成線程調度并提供相應的系統調用,用戶程序可以通過這些接口函數對線程進行一定的控制和管理。Linux操作系統提供了LinuxThreads庫,它是符合POSIX1003.1c標準的內核級多線程函數庫。在linuxthreads庫中提供了一些多線程編程的關鍵函數,在多線程編程時應包括pthread.h文件。 2.LinuxThread中的關鍵庫函數 2.1線程的創建和終止 int pthread_create(pthread_t * pthread,const pthread_attr_t *attr,void *(*start_routine(*void)),void *arg);調用此函數可以創建一個新的線程,新線程創建后執行start_routine 指定的程序。其中參數attr是用戶希望創建線程的屬性,當為NULL時表示以默認的屬性創建線程。arg是向start_routine 傳遞的參數。當成功創建一個新的線程時,系統會自動為新線程分配一個線程ID號,并通過pthread 返回給調用者。 void pthread_exit(void *value_ptr);調用該函數可以退出線程,參數value_ptr是一個指向返回狀態值的指針。 2.2線程控制函數 pthread_self(void);為了區分線程,在線程創建時系統為其分配一個唯一的ID號,由pthread_create()返回給調用者,也可以通過pthread_self()獲取自己的線程ID。 Int pthread_join (pthread- t thread , void * *status);這個函數的作用是等待一個線程的結束。調用pthread_join()的線程將被掛起直到線程ID為參數thread 指定的線程終止。 int pthread_detach(pthread_t pthread);參數pthread代表的線程一旦終止,立即釋放調該線程占有的所有資源。 2.3線程間的互斥 互斥量和臨界區類似,只有擁有互斥量的線程才具有訪問資源的權限,由于互斥對象只有一個,這就決定了任何情況下共享資源(代碼或變量)都不會被多個線程同時訪問。使用互斥不僅能夠在同一應用程序的不同線程中實現資源的安全共享,而且可以在不同應用程序的線程之間實現對資源的安全共享。Linux中通過pthread_mutex_t來定義互斥體機制完成互斥操作。具體的操作函數如下 pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);初使化一個互斥體變量mutex,參數attr表示按照attr屬性創建互斥體變量mutex,如果參數attr為NULL,則以默認的方式創建。 pthread_mutex_lock(pthread_mutex_t *mutex);給一個互斥體變量上鎖,如果mutex指定的互斥體已經被鎖住,則調用線程將被阻塞直到擁有mutex的線程對mutex解鎖為止。 Pthread_mutex_unlock(pthread_mutex_t *mutex);對參數mutex指定的互斥體變量解鎖。 2.4線程間的同步 同步就是線程等待某一個事件的發生,當等待的事件發生時,被等待的線程和事件一起繼續執行。如果等待的事件未到達則掛起。在linux操作系統中是通過條件變量來實現同步的。 Pthread_cond_init(pthread_cond_t *cond,const pthread_cond_t *attr);這個函數按參數attr指定的屬性初使化一個條件變量cond。 Pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);等待一個事件(條件變量)的發生,發出調用的線程自動阻塞,直到相應的條件變量被置1。等待狀態的線程不占用CPU時間。 pthread_cond_signal(pthread_cond_t *cond);解除一個等待參數cond指定的條件變量的線程的阻塞狀態。 3.多線程編程的應用實例。 在這里利用多線程技術實現生產者和消費者問題,生產者線程向一緩沖區中寫數據,消費者線程從緩沖區中讀取數據,由于生產者線程和消費者線程共享同一緩沖區,為了正確讀寫數據,在使用緩沖隊列時必須保持互斥。生產者線程和消費者線程必須滿足:生產者寫入緩沖區的數目不能超過緩沖區容量,消費者讀取的數目不能超過生產者寫入的數目。在程序中使用了一個小技巧來判斷緩沖區是空還是滿。在初始化時讀指針和寫指針為0;如果讀指針等于寫指針,則緩沖區是空的;如果(寫指針+ 1) % N 等于讀指針,則緩沖區是滿的,%表示取余數,這時實際上有一個單元空出未用。下面是完整的程序段和注釋。


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

#define BUFFER_SIZE 8

struct prodcons {
??? int buffer[BUFFER_SIZE];
??? pthread_mutex_t lock;????? //互斥LOCK
??? int readpos , writepos;
??? pthread_cond_t notempty;?? //緩沖區非空條件判斷
??? pthread_cond_t notfull;??? //緩沖區未滿條件判斷
};

void init(struct prodcons * b){
??? pthread_mutex_init(&b->lock,NULL);
??? pthread_cond_init(&b->notempty,NULL);
??? pthread_cond_init(&b->notfull,NULL);

??? b->readpos=0;
??? b->writepos=0;
}

void put(struct prodcons* b,int data){
??? pthread-_mutex_lock(&b->lock);

??? if((b->writepos + 1) % BUFFER_SIZE == b->readpos)
??? {
??????? pthread_cond_wait(&b->notfull, &b->lock) ;
??? }
???
??? b->buffer[b->writepos]=data;
??? b->writepos++;
???
??? if(b->writepos >= BUFFER_SIZE)
??????? b->writepos=0;
???
??? pthread_cond_signal(&b->notempty);
??? pthread_mutex_unlock(&b->lock);
}
int get(struct prodcons *b){
??? int data;

??? pthread_mutex_lock(&b->lock);
??? if(b->writepos == b->readpos)
??? {
??????? pthread_cond _wait(&b->notempty, &b->lock);
??? }
???
??? data = b->buffer[b->readpos];
??? b->readpos++;

??? if(b->readpos >= BUFFER_SIZE)
??????? b->readpos=0;
???
??? pthread_cond_signal(&b->notfull);
??? pthread_mutex_unlock(&b->lock);

??? return data;
}

#define OVER (-1)
struct prodcons buffer;

void *producer(void *data)
{
??? int n;
???
??? for(n = 0; n < 10000; n++)
??? {
??????? printf("%d \n", n) ;
??????? put(&buffer, n);
??? }
???
??? put(&buffer, OVER);
???
??? return NULL;
}
void *consumer(void * data)
{
??? int d;
???
??? while(1)
??? {
??????? d = get(&buffer);

??????? if(d == OVER)
??????????? break;
???????
??????? printf("%d\n", d);
??? }

??? return NULL;
}

int main(void)
{
??? pthread_t th_a, th_b;
???
??? void *retval;
???
??? init(&buffer);
???
??? pthread_create(&th_a, NULL, producer, 0);
??? pthread_create(&th_b, NULL, consumer, 0);
???
??? pthread_join(th_a, &retval);
??? pthread_join(th_b, &retval);
???
??? return 0;
}



上面的例子中,生產者負責將1到1000的整數寫入緩沖區,而消費者負責從同一個緩沖區中讀取寫入的整數并打印出來。因為生產者和消費者是兩個同時運行的線程,并且要使用同一個緩沖區進行數據交換,因此必須利用一種機制進行同步。通過上面的例子我們可以看到,多線程的最大好處是,除堆棧之外,幾乎所有的數據均是共享的,因此線程間的通訊效率很高;缺點:因為共享所有數據,從而非常容易導致線程之間互相破壞數據,這一點在編程時必須注意。 4.結束語 Linux中基于POSIX標準的很好的支持了多線程技術,它減少了程序并發執行時的系統開銷,提高了計算機的工作效率。在具體編程過程中要了解線程的間的關系,還要考慮共享數據的保護,在互斥和同步機制下保證代碼的高效運行,程序編譯時用gcc -D –REENTRANT -libpthread.xx.so filename.c編譯。

?

?

轉載于:https://www.cnblogs.com/james1207/p/3299413.html

總結

以上是生活随笔為你收集整理的linux中多线程解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。