这是一个书上的例子,逻辑是:一个线程生产一组数字1、2、3..... 等等,放入一个循环队列中。另一个线程去处理这些数字,达到的效果是把这些数字求和。还是看看代码吧。
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <semaphore.h>
#define BUFSIZE 4
#define NUMBER 8
int sum_of_number=0;
/* 可读 和 可写资源数*/
sem_t write_res_number;
sem_t read_res_number;
/* 循环队列 */
struct recycle_buffer{
int buffer[BUFSIZE];
int head,tail;
}re_buf;
/* 用于实现临界区的互斥锁,我们对其初始化*/
pthread_mutex_t buffer_mutex=PTHREAD_MUTEX_INITIALIZER;
static void *producer(void * arg)
{
int i;
for(i=0;i<=NUMBER;i++)
{
/* 减少可写的资源数 */
sem_wait(&write_res_number);
/* 进入互斥区 */
pthread_mutex_lock(&buffer_mutex);
/*将数据复制到缓冲区的尾部*/
re_buf.buffer[re_buf.tail]=i;
re_buf.tail=(re_buf.tail+1)%BUFSIZE;
printf("procuder %d write %d.\n",pthread_self(),i);
/*离开互斥区*/
pthread_mutex_unlock(&buffer_mutex);
/*增加可读资源数*/
sem_post(&read_res_number);
}
/* 线程终止,如果有线程等待它们结束,则把NULL作为等待其结果的返回值*/
return NULL;
}
static void * consumer(void * arg)
{
int i,num;
for(i=0;i<=NUMBER;i++)
{
/* 减少可读资源数 */
sem_wait(&read_res_number);
/* 进入互斥区*/
pthread_mutex_lock(&buffer_mutex);
/* 从缓冲区的头部获取数据*/
num = re_buf.buffer[re_buf.head];
re_buf.head = (re_buf.head+1)%BUFSIZE;
printf("consumer %d read %d.\n",pthread_self(),num);
/* 离开互斥区*/
pthread_mutex_unlock(&buffer_mutex);
sum_of_number+=num;
/* 增加客写资源数*/
sem_post(&write_res_number);
}
/* 线程终止,如果有线程等待它们结束,则把NULL作为等待其结果的返回值*/
return NULL;
}
int main(int argc,char ** argv)
{
/* 用于保存线程的线程号 */
pthread_t p_tid;
pthread_t c_tid;
int i;
re_buf.head=0;
re_buf.tail=0;
for(i=0;i<BUFSIZE;i++)
re_buf.buffer[i] =0;
/* 初始化可写资源数为循环队列的单元数 */
sem_init(&write_res_number,0,BUFSIZE); // 这里限定了可写的bufsize,当写线程写满buf时,会阻塞,等待读线程读取
/* 初始化可读资源数为0 */
sem_init(&read_res_number,0,0);
/* 创建两个线程,线程函数分别是 producer 和 consumer */
/* 这两个线程将使用系统的缺省的线程设置,如线程的堆栈大小、线程调度策略和相应的优先级等等*/
pthread_create(&p_tid,NULL,producer,NULL);
pthread_create(&c_tid,NULL,consumer,NULL);
/*等待两个线程完成退出*/
pthread_join(p_tid,NULL);
pthread_join(c_tid,NULL);
printf("The sun of number is %d\n",sum_of_number);
}
编译命令:gcc -g -o threadtest threadtest.c -lpthread
分享到:
相关推荐
本文将详细介绍Linux环境下C语言编程中的几种进程通信方法,包括POSIX无名信号量、System V信号量、System V消息队列以及System V共享内存。 #### 1. POSIX无名信号量 ##### 理论基础 信号量是一种用于控制多个...
在Linux系统编程中,线程同步与互斥是多线程程序设计中至关重要的概念,它们确保了共享资源的安全访问,防止数据竞争和死锁等问题。无名信号量是一种常用的同步机制,它允许线程之间通过计数值进行通信,以控制对...
- POSIX匿名信号量和系统V IPC的信号量都是用于控制资源访问的计数器,实现线程同步。 - 线程取消和线程死锁是线程编程中需要考虑的问题,例如`pthread_cancel()`用于取消线程,死锁则需通过避免循环等待条件来...
进程间通信(IPC)方式包括共享内存、消息队列、信号量、有名管道、无名管道、信号和socket等,这些通信方式通常涉及到上下文切换,速度相对较慢。 - **线程**:是进程内的执行单元,共享进程资源,如内存空间。每...
- **无名信号量(Anon Semaphores)**:适用于同一进程的不同线程之间的同步。 - **命名信号量(Named Semaphores)**:允许多个不同进程间的同步,通常通过`sem_open()`创建。 信号量的基本操作包括`P`(减锁)、`...
- 信号量用于解决进程间的同步问题,无名信号量适用于同一进程内的线程间同步。 - **SystemV信号量** - SystemV信号量提供了跨进程的同步机制。 - **SystemV消息队列** - 消息队列允许进程之间传递结构化的数据。...
共享内存是一种效率较高的IPC方式,允许多个进程共享同一段内存空间,但是需要使用信号量来实现同步和互斥。消息队列则是基于消息的发送和接收来进行进程间的通信。 Linux系统信号处理也是进程编程中的一大重点。...
通过对生产者-消费者模型的实现,学生将学习如何在Linux环境下运用无名信号量来保护临界资源,同时提升对文件I/O操作的掌握。 二、实验内容 实验分为三个部分: 1. 使用链式结构创建10个子进程,形成进程链。 2. ...
信号量是操作系统中用于多任务环境下资源管理的一种机制,尤其在Linux系统中,信号量在进程和线程同步中扮演着关键角色。它们主要用于保护共享资源,确保在某一时刻只有一个进程或线程能够访问特定的资源,避免因...
在Linux操作系统中,进程和线程是两个核心概念,它们是程序...通过学习这个教程,你将能够熟练掌握Linux环境下的进程与线程管理,以及如何利用信号量、管道和共享内存实现进程间有效通信,为系统级编程打下坚实的基础。
无名信号量是POSIX标准中定义的同步机制,它允许操作系统的进程和线程对共享资源进行互斥访问和同步。无名信号量不通过文件描述符进行访问,而是在进程的地址空间内操作,因此只能在创建它们的进程中使用,无法跨...
- 互斥确保同一时间只有一个线程访问资源,而同步则控制线程的执行顺序,通常使用互斥锁和信号量等机制实现。 10. **特殊进程类型**: - 僵尸进程是已退出但其父进程未收集其退出状态的进程。孤儿进程是父进程...
在Linux中,线程由pthread库提供,`pthread_create()`用于创建新线程,`pthread_join()`等待线程结束,`pthread_mutex_*`系列函数用于互斥锁实现线程同步,防止竞态条件。线程局部存储(TLS, Thread Local Storage)...
9. **进程间通信(IPC)**:Linux提供了多种进程间通信方式,如管道(无名管道和命名管道)、消息队列、共享内存、信号量等,这些都用于不同进程之间的数据交换和协调。 10. **系统调用接口(System Call Interface...
无名信号量(内存信号量): sem_t, p, v, 互斥锁:pthread_mutex_t 进程: Fork()/ execve();// system(); 进程内存空间 环境变量: 从哪里来, 放在那里, 如何取用 进程通信: 传统: 无名管道 pipe: 亲缘...
在Linux中,实现了POSIX无名信号量,这些信号量可以在线程间共享。以下是一些重要的函数: 1. `sem_init`:用于创建信号量,并设定其初始值。第二个参数`pshared`在当前的Linux实现中必须为0,意味着信号量仅限于...