Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Analisis kod contoh pengaturcaraan berbilang benang Linux

Analisis kod contoh pengaturcaraan berbilang benang Linux

王林
王林ke hadapan
2023-05-26 22:04:041545semak imbas

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&#39;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&#39;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&#39;m thread 1
thread1 : number = 0
thread2 : i&#39;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.

Tiga pthread_join pthread_exit

 
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

Kunci Mutex digunakan untuk memastikan hanya satu utas melaksanakan sekeping kod dalam tempoh masa.

pthread_mutex_init

Fungsi pthread_mutex_init digunakan untuk menjana kunci mutex. Parameter nol menunjukkan bahawa sifat lalai digunakan. Jika anda perlu mengisytiharkan mutex untuk atribut tertentu, anda mesti memanggil fungsi pthread_mutecasttr_init. Fungsi pthread_mutecasttr_setpshared dan fungsi pthread_mutecasttr_settype digunakan untuk menetapkan atribut kunci mutex. Fungsi sebelumnya menetapkan atribut pshared, yang mempunyai dua nilai, pthread_process_private dan pthread_process_shared. Yang pertama digunakan untuk menyegerakkan benang dalam proses yang berbeza, dan yang terakhir digunakan untuk menyegerakkan benang yang berbeza dalam proses ini. Dalam contoh di atas, kami menggunakan atribut lalai pthread_process_private. Yang terakhir digunakan untuk menetapkan jenis kunci mutex Jenis pilihan ialah pthread_mutex_normal, pthread_mutex_errorcheck, pthread_mutex_recursive dan pthread _mutex_default. Mereka masing-masing mentakrifkan mekanisme penyenaraian dan buka kunci yang berbeza Dalam keadaan biasa, atribut lalai terakhir dipilih.

Dua pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

Pernyataan pthread_mutex_lock mula dikunci dengan kunci mutex Kod seterusnya dikunci sehingga pthread_mutex_cut exe hanya boleh dipanggil, iaitu, ia dipanggil dengan satu utas. pada masa yang sama. Apabila benang melaksanakan pthread_mutex_lock, jika kunci digunakan oleh benang lain pada masa ini, benang disekat, iaitu program akan menunggu sehingga benang lain melepaskan kunci mutex.

Nota:

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!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam