首页 > 娱乐影音->c语言线程间通信的几种方法(C语言实现线程间通信的几种方式)

c语言线程间通信的几种方法(C语言实现线程间通信的几种方式)

jk+ 论文 5451 次浏览 评论已关闭

C语言实现线程间通信的几种方式

线程间通信是多线程编程中的一个基本议题。线程间通信在多线程编程实践中非常重要,也是多线程编程中的一个基础知识。可以通过多种方式实现线程间通信,本文将介绍C语言中的几种常用方式。

信号量

信号量是一种同步机制,用于控制对共享资源的访问。在C语言中,使用信号量可以实现线程间的同步和互斥。通过使用信号量,可以确保一次只有一个线程访问资源,而其他线程则被阻塞,直到占用资源的线程释放它。信号量的实现依赖于系统,一般情况下,在Linux和Windows操作系统中都提供了信号量的支持。

下面是一个使用信号量实现线程间同步的例子:

``` #include #include #include #include #defineMAX_THREAD_NUM5 #defineWORK_TIMES5 intg_count=0; sem_tsem; void*thread_func(void*arg) { inti; for(i=0;i在上面的例子中,使用信号量sem来控制对全局变量g_count的访问,每个线程执行一定次数的工作,并对g_count进行更新。由于信号量的初始值为1,所以第一个访问g_count的线程不会被阻塞,其他线程则一次只能有一个线程访问g_count。在每个线程对g_count进行修改之前,使用sem_wait函数对sem进行P操作,从而实现互斥访问。在修改完成之后,使用sem_post函数对sem进行V操作,唤醒其他被阻塞的线程。

条件变量

条件变量是一种同步机制,用于线程间通信。在C语言中,使用条件变量可以灵活的实现生产者-消费者模型、读写者模型等场景。当某个条件不满足时,线程可以通过条件变量等待,等待相应的条件满足后再被唤醒。条件变量的实现依赖于系统,一般情况下,在Linux和Windows操作系统中都提供了条件变量的支持。

下面是一个使用条件变量实现生产者-消费者模型的例子:

``` #include #include #include #defineBUFFER_SIZE10 #defineMAX_ITEM_NUM100 intg_buffer[BUFFER_SIZE]; intg_front=0,g_rear=0; intg_item_count=0; pthread_mutex_tmutex; pthread_cond_tcond; void*producer_func(void*arg) { intitem=0; while(1) { pthread_mutex_lock(&mutex); if(g_item_count==MAX_ITEM_NUM) { pthread_cond_wait(&cond,&mutex); } item++; g_buffer[g_rear]=item; g_rear=(g_rear+1)%BUFFER_SIZE; g_item_count++; printf(\"producerproduceditem%d,count=%d\ \",item,g_item_count); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); sleep(1); } pthread_exit(NULL); } void*consumer_func(void*arg) { intitem; while(1) { pthread_mutex_lock(&mutex); if(g_item_count==0) { pthread_cond_wait(&cond,&mutex); } item=g_buffer[g_front]; g_front=(g_front+1)%BUFFER_SIZE; g_item_count--; printf(\"consumerconsumeditem%d,count=%d\ \",item,g_item_count); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); sleep(1); } pthread_exit(NULL); } intmain(intargc,char*argv[]) { pthread_tproducer_thread,consumer_thread; pthread_mutex_init(&mutex,NULL); pthread_cond_init(&cond,NULL); pthread_create(&producer_thread,NULL,producer_func,NULL); pthread_create(&consumer_thread,NULL,consumer_func,NULL); pthread_join(producer_thread,NULL); pthread_join(consumer_thread,NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); return0; } ```

在上面的例子中,使用条件变量cond实现了一个生产者-消费者模型。生产者线程负责生产数据,消费者线程负责消费数据。多个生产者和消费者线程可以同时进行工作,而使用条件变量即可得到正确的结果。在生产者的生产之前,如果缓冲区已满,则使用pthread_cond_wait函数等待条件变量cond。当消费者消费掉一些数据后,即释放了一些缓存空间,生产者线程又可以从前面的条件变量处返回,继续进行生产。每当生产者线程生产一个数据后,都会使用pthread_cond_signal函数唤醒消费者线程,消费者在消费一个数据之后,也会进行相同的操作,在消费完一个数据之后,唤醒生产者线程。

管道

管道是一种基本的进程间通信方式。在C语言中,使用管道(pipe)可以实现父进程和子进程之间的通信,也可以用于线程间通信。在管道中,一个进程向管道写入数据,另一个进程从管道读取数据。管道具有缓冲的能力,当数据流进来时缓冲区满了,会暂停写入数据,缓冲区空闲时又可以继续写入数据。在管道中,父进程和子进程只能单向的进行数据通信,无法进行双向通信。

下面是一个使用管道进行线程间通信的例子:

``` #include #include #include #include #defineBUFFER_SIZE1024 intg_fd[2]; void*write_thread(void*arg) { charbuffer[BUFFER_SIZE]; inti=0; for(i=0;i<5;i++) { sprintf(buffer,\"message%dfromwrite_thread\ \",i+1); write(g_fd[1],buffer,sizeof(buffer)); sleep(1); } pthread_exit(NULL); } void*read_thread(void*arg) { charbuffer[BUFFER_SIZE]; intnbytes; while(1) { nbytes=read(g_fd[0],buffer,sizeof(buffer)); if(nbytes==0) { break; } printf(\"%s\",buffer); } pthread_exit(NULL); } intmain(intargc,char*argv[]) { pthread_twrite_tid,read_tid; if(pipe(g_fd)<0) { printf(\"pipeerror!\ \"); return0; } pthread_create(&write_tid,NULL,write_thread,NULL); pthread_create(&read_tid,NULL,read_thread,NULL); pthread_join(write_tid,NULL); close(g_fd[1]); pthread_join(read_tid,NULL); close(g_fd[0]); return0; } ```

上面的例子中创建了一个管道g_fd,该管道的读写文件描述符分别为g_fd[0]和g_fd[1]。在写线程中,将一些数据写入管道中,而在读线程中,从管道中读取数据。在主线程中,使用函数close函数关闭了读写文件描述符,最终等待读线程结束。

以上三种方法都是很好的线程间通信的方式,具体的使用场景根据不同的情况可以选择采用不同的方式。