Rumah > Artikel > Operasi dan penyelenggaraan > Analisis kod contoh pengaturcaraan berbilang benang Linux
Mari kita ambil contoh dahulu. Kami mencipta dua utas untuk menambah nombor. Mungkin contoh ini tidak mempunyai nilai praktikal, tetapi dengan sedikit perubahan, kita boleh menggunakannya di tempat lain.
Kod:
/*thread_example.c : c multiple thread programming in linux *author : falcon *e-mail : tunzhj03@st.lzu.edu.cn */ #include <pthread.h> #include <stdio.h> #include <sys/time.h> #include <string.h> #define max 10 pthread_t thread[2]; pthread_mutex_t mut; int number=0, i; void *thread1() { printf ("thread1 : i'm thread 1/n"); for (i = 0; i < max; i++) { printf("thread1 : number = %d/n",number); pthread_mutex_lock(&mut); number++; pthread_mutex_unlock(&mut); sleep(2); } printf("thread1 :主函数在等我完成任务吗?/n"); pthread_exit(null); } void *thread2() { printf("thread2 : i'm thread 2/n"); for (i = 0; i < max; i++) { printf("thread2 : number = %d/n",number); pthread_mutex_lock(&mut); number++; pthread_mutex_unlock(&mut); sleep(3); } printf("thread2 :主函数在等我完成任务吗?/n"); pthread_exit(null); } void thread_create(void) { int temp; memset(&thread, 0, sizeof(thread)); //comment1 /*创建线程*/ if((temp = pthread_create(&thread[0], null, thread1, null)) != 0) //comment2 printf("线程1创建失败!/n"); else printf("线程1被创建/n"); if((temp = pthread_create(&thread[1], null, thread2, null)) != 0) //comment3 printf("线程2创建失败"); else printf("线程2被创建/n"); } void thread_wait(void) { /*等待线程结束*/ if(thread[0] !=0) { //comment4 pthread_join(thread[0],null); printf("线程1已经结束/n"); } if(thread[1] !=0) { //comment5 pthread_join(thread[1],null); printf("线程2已经结束/n"); } } int main() { /*用默认属性初始化互斥锁*/ pthread_mutex_init(&mut,null); printf("我是主函数哦,我正在创建线程,呵呵/n"); thread_create(); printf("我是主函数哦,我正在等待线程完成任务阿,呵呵/n"); thread_wait(); return 0; }
Mari kita susun dan laksanakannya dahulu
Petikan:
falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c falcon@falcon:~/program/c/code/ftp$ ./thread_example 我是主函数哦,我正在创建线程,呵呵 线程1被创建 线程2被创建 我是主函数哦,我正在等待线程完成任务阿,呵呵 thread1 : i'm thread 1 thread1 : number = 0 thread2 : i'm thread 2 thread2 : number = 1 thread1 : number = 2 thread2 : number = 3 thread1 : number = 4 thread2 : number = 5 thread1 : number = 6 thread1 : number = 7 thread2 : number = 8 thread1 : number = 9 thread2 : number = 10 thread1 :主函数在等我完成任务吗? 线程1已经结束 thread2 :主函数在等我完成任务吗? 线程2已经结束
Komen dalam kod contoh hendaklah lebih jelas, di bawah saya telah memetik beberapa fungsi dan pembolehubah yang dinyatakan di atas di Internet.
Petikan:
Operasi berkaitan benang
Satu pthread_t
pthread_t ditakrifkan dalam fail pengepala /usr/include/bits/pthreadtypes.h:
Typedef unsigned long int pthread_t;
Ia ialah pengecam sesuatu benang.
Two pthread_create
Fungsi pthread_create digunakan untuk mencipta thread Prototaipnya ialah:
extern int pthread_create __p ((pthread_t *__thread, __const pthread_attr_t *. * (*__start_routine) (void *), void *__arg));
Parameter pertama ialah penunjuk kepada pengecam benang, parameter kedua digunakan untuk menetapkan atribut benang, dan parameter ketiga ialah fungsi permulaan bagi fungsi thread running Alamat permulaan, parameter terakhir ialah parameter untuk menjalankan fungsi. Di sini, utas fungsi kami tidak memerlukan parameter, jadi parameter terakhir ditetapkan kepada penuding nol. Kami juga menetapkan parameter kedua kepada penuding nol, yang akan menghasilkan benang dengan atribut lalai. Kami akan menerangkan tetapan dan pengubahsuaian atribut benang dalam bahagian seterusnya. Apabila benang berjaya dibuat, fungsi mengembalikan 0. Jika bukan 0, penciptaan benang gagal Kod pulangan ralat biasa adalah eagain dan einval. Yang pertama bermakna sistem mengehadkan penciptaan utas baharu, contohnya, bilangan utas terlalu banyak bermakna nilai atribut utas yang diwakili oleh parameter kedua adalah haram. Selepas utas berjaya dibuat, utas yang baru dibuat menjalankan fungsi yang ditentukan oleh parameter tiga dan parameter empat, dan utas asal terus menjalankan baris kod seterusnya.
Fungsi pthread_join digunakan untuk menunggu penghujung thread. Prototaip fungsi ialah:
extern int pthread_join __p ((pthread_t __th, void **__thread_return)); Boleh digunakan untuk menyimpan nilai pulangan benang menunggu. Fungsi ini ialah fungsi menyekat benang Fungsi memanggilnya akan menunggu sehingga utas menunggu tamat Apabila fungsi kembali, sumber benang menunggu dipulihkan. Terdapat dua cara untuk menamatkan utas satu adalah seperti contoh di atas Apabila fungsi berakhir, utas yang memanggilnya juga berakhir. Prototaip fungsinya ialah:
extern void pthread_exit __p ((void *__retval)) __attribute__ ((__noreturn__)); bukan null , nilai ini akan dihantar ke thread_return. Perkara terakhir yang perlu diambil perhatian ialah satu utas tidak boleh ditunggu oleh berbilang utas, jika tidak, utas pertama yang menerima isyarat berjaya dikembalikan, dan utas selebihnya yang memanggil pthread_join mengembalikan kod ralat esrch.
Dalam bahagian ini, kami menulis urutan yang paling mudah dan menguasai tiga fungsi yang paling biasa digunakan pthread_create, pthread_join dan pthread_exit. Seterusnya, mari kita pelajari tentang beberapa sifat biasa benang dan cara menetapkannya.
Berkaitan kunci Mutex
1 Perlu diingat bahawa dua tidur di atas bukan sahaja untuk tujuan demonstrasi, tetapi juga untuk membiarkan benang tidur untuk satu tempoh masa, biarkan benang melepaskan kunci mutex, dan tunggu benang lain menggunakan kunci ini . Masalah ini dijelaskan dalam Rujukan 1 di bawah. Walau bagaimanapun, nampaknya tiada fungsi pthread_delay_np di bawah Linux (saya mencubanya dan ia digesa bahawa tiada rujukan kepada fungsi yang ditakrifkan), jadi saya menggunakan tidur sebaliknya, kaedah lain diberikan dalam Rujukan 2, yang nampaknya digantikan dengan pthread_cond_timedwait , yang memberikan cara untuk mencapainya.
2 Sila beri perhatian kepada komen 1-5 di dalam. Itulah masalah yang saya ambil masa beberapa jam untuk mengetahuinya.
Jika tiada komen1, komen4 dan komen5, ia akan menyebabkan segfault semasa pthread_join Selain itu, komen2 dan komen3 di atas adalah punca, jadi pastikan anda ingat untuk menulis keseluruhan kod. Oleh kerana utas di atas mungkin tidak berjaya dibuat, adalah mustahil untuk menunggu utas itu tamat, dan ralat segmentasi berlaku (kawasan memori yang tidak diketahui diakses) apabila menggunakan pthread_join. Selain itu, apabila menggunakan memset, anda perlu memasukkan fail pengepala string.h
Atas ialah kandungan terperinci Analisis kod contoh pengaturcaraan berbilang benang Linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!