您的位置:

c语言pthreadcondt,c语言pthread_join

本文目录一览:

在linux下用c语言实现用多进程同步方法演示“生产者-消费者”问题

这个问题需要的知识主要包括:

1 多进程间进行通信;

2 使用同步信号量(semaphore)和互斥信号量(mutex)进行数据保护。

参考代码如下,可以参照注释辅助理解:

#include stdio.h

#include stdlib.h

#include unistd.h

#include pthread.h

#include semaphore.h

#define N 2   // 消费者或者生产者的数目

#define M 10 // 缓冲数目

int in = 0;   // 生产者放置产品的位置

int out = 0; // 消费者取产品的位置

int buff[M] = {0}; // 缓冲初始化为0, 开始时没有产品

sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品

sem_t full_sem;   // 同步信号量, 当没产品时阻止消费者消费

pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲

int product_id = 0;   //生产者id

int prochase_id = 0; //消费者id

/* 打印缓冲情况 */

void print()

{

int i;

for(i = 0; i  M; i++)

   printf("%d ", buff[i]);

printf("\n");

}

/* 生产者方法 */ 

void *product()

{

int id = ++product_id;

while(1)

{

   // 用sleep的数量可以调节生产和消费的速度,便于观察

   sleep(1);

   //sleep(1);

  

   sem_wait(empty_sem);

   pthread_mutex_lock(mutex);

  

   in = in % M;

   printf("product%d in %d. like: \t", id, in);

  

   buff[in] = 1;  

   print();  

   ++in;

  

   pthread_mutex_unlock(mutex);

   sem_post(full_sem);  

}

}

/* 消费者方法 */

void *prochase()

{

int id = ++prochase_id;

while(1)

{

   // 用sleep的数量可以调节生产和消费的速度,便于观察

   sleep(1);

//sleep(1);

  

   sem_wait(full_sem);

   pthread_mutex_lock(mutex);

  

   out = out % M;

   printf("prochase%d in %d. like: \t", id, out);

  

   buff[out] = 0;

   print();

   ++out;

  

   pthread_mutex_unlock(mutex);

   sem_post(empty_sem);

}

}

int main()

{

pthread_t id1[N];

pthread_t id2[N];

int i;

int ret[N];

// 初始化同步信号量

int ini1 = sem_init(empty_sem, 0, M); 

int ini2 = sem_init(full_sem, 0, 0);  

if(ini1  ini2 != 0)

{

   printf("sem init failed \n");

   exit(1);

//初始化互斥信号量 

int ini3 = pthread_mutex_init(mutex, NULL);

if(ini3 != 0)

{

   printf("mutex init failed \n");

   exit(1);

// 创建N个生产者线程

for(i = 0; i  N; i++)

{

   ret[i] = pthread_create(id1[i], NULL, product, (void *)(i));

   if(ret[i] != 0)

   {

    printf("product%d creation failed \n", i);

    exit(1);

   }

}

//创建N个消费者线程

for(i = 0; i  N; i++)

{

   ret[i] = pthread_create(id2[i], NULL, prochase, NULL);

   if(ret[i] != 0)

   {

    printf("prochase%d creation failed \n", i);

    exit(1);

   }

}

//销毁线程

for(i = 0; i  N; i++)

{

   pthread_join(id1[i],NULL);

   pthread_join(id2[i],NULL);

}

exit(0); 

}

在Linux下编译的时候,要在编译命令中加入选项-lpthread以包含多线程支持。比如存储的C文件为demo.c,要生成的可执行文件为demo。可以使用命令:

gcc demo.c -o demo -lpthread

程序中为便于观察,使用了sleep(1);来暂停运行,所以查看输出的时候可以看到,输出是每秒打印一次的。

如何使用pthread

怎样知道一个pthread

如果需要只终止某个线程而不终止整个进程,可以有三种方法:

1.从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。

2.一个线程可以调用pthread_cancel终止同一进程中的另一个线程。

3.线程可以调用pthread_exit终止自己。

使用条件变量进行线程间的同步

先看一下APUE第三版对于条件变量的说明:

条件变量是另一种线程同步机制,它为线程间共享的对象提供了同步的方法。当条件变量配合互斥锁(Mutex)使用时,允许多个线程处在一种自由等待任意条件发生的状态。

条件变量自身由互斥锁(Mutex)保护。线程必须在修改条件状态之前先对其上锁,其他线程不会在获取锁之前被通知到其状态变化,因为只有获取到锁才可以计算条件。

条件变量的数据类型是 pthread_cond_t ,条件变量属性的类型是 pthread_condattr_t ,它们都包含在头文件pthread.h中。

条件变量使用之前必须初始化,有两种方法:

需要释放条件变量时,使用pthread_cond_destroy即可。

调用phread_cond_wait或pthread_cond_timewait(以下简称wait函数)可以使当前线程等待某一条件的发生。两者的区别在于后者可以指定等待时间。

调用wait函数时,系统使调用线程进入等待状态后 释放锁 (所以我们必须先加锁后调用wait函数)。在这一步操作中的检查条件和进入等待是 原子操作 ,所以线程不会错过条件的变化。当wait函数返回时,mutex会 再次被加锁 。

其中pthread_cond_timewait中用到的timespec结构定义如下:

需要注意的是,timespec是一个绝对时间,所以在使用前我们需要先取得当前时间,再加上等待时间。例如下面这样:

如果时间到了还没有等到条件变化,函数会对mutex重新加锁并返回一个ETIMEOUT的错误。

当wait函数返回成功时, 需要重新检查条件 ,因为条件有可能已经被其他线程修改。

当条件满足时,可以用这两个函数用来通知其他线程。

pthread_cond_signal会唤醒至少一个等待的线程,而pthread_cond_broadcast会唤醒所有等待的线程。必须注意的是:我们 必须在状态发生变化之后再发送信号给其他线程 。

条件变量的数据类型是 pthread_cond_t ,它主要有两种属性:

设置进程间共享属性:

设置时钟属性:

pthread_cond_timewait函数用于在等待条件变量时提供超时功能,不过该函数的超时时间是一个绝对时间。默认使用系统时间,这意味着若修改系统时间,那么超时就不准确:有可能提前返回,也可能要几年才返回。这在某些情况下会导致bug,这时我们可以通过设置条件变量的时钟属性来避免这个问题。下面的例子展示了如何使用这个属性:

Linux C语言pthread_mutex_unlock和pthread_cond_signal顺序问题

signal前解锁是错误,顺序相当重要,锁才能保证你整个操作是完全原子,signal只是整个操作的一部分,它不能被分割出去。用特殊一点的情况来解释:如果解锁后才signal,那么有可能信号一直发不出去,因为信号线程一直得到不调度。

C语言如何终止线程?

面只有两个线程,是生产者/消费者模式,已编译通过,注释很详细。

/* 以生产者和消费者模型问题来阐述Linux线程的控制和通信你

生产者线程将生产的产品送入缓冲区,消费者线程则从中取出产品。

缓冲区有N个,是一个环形的缓冲池。

*/

#include stdio.h

#include pthread.h

#define BUFFER_SIZE 16

struct prodcons

{

int buffer[BUFFER_SIZE];/*实际存放数据的数组*/

pthread_mutex_t lock;/*互斥体lock,用于对缓冲区的互斥操作*/

int readpos,writepos; /*读写指针*/

pthread_cond_t notempty;/*缓冲区非空的条件变量*/

pthread_cond_t notfull;/*缓冲区未满 的条件变量*/

};

/*初始化缓冲区*/

void pthread_init( struct prodcons *p)

{

pthread_mutex_init(p-lock,NULL);

pthread_cond_init(p-notempty,NULL);

pthread_cond_init(p-notfull,NULL);

p-readpos = 0;

p-writepos = 0;

}

/*将产品放入缓冲区,这里是存入一个整数*/

void put(struct prodcons *p,int data)

{

pthread_mutex_lock(p-lock);

/*等待缓冲区未满*/

if((p-writepos +1)%BUFFER_SIZE ==p-readpos)

{

pthread_cond_wait(p-notfull,p-lock);

}

p-buffer[p-writepos] =data;

p-writepos++;

if(p-writepos = BUFFER_SIZE)

p-writepos = 0;

pthread_cond_signal(p-notempty);

pthread_mutex_unlock(p-lock);

}

/*从缓冲区取出整数*/

int get(struct prodcons *p)

{

int data;

pthread_mutex_lock(p-lock);

/*等待缓冲区非空*/

if(p-writepos == p-readpos)

{

pthread_cond_wait(p-notempty ,p-lock);//非空就设置条件变量notempty

}

/*读书据,移动读指针*/

data = p-buffer[p-readpos];

p-readpos++;

if(p-readpos == BUFFER_SIZE)

p-readpos = 0;

/*设置缓冲区未满的条件变量*/

pthread_cond_signal(p-notfull);

pthread_mutex_unlock(p-lock);

return data;

}

/*测试:生产站线程将1 到1000的整数送入缓冲区,消费者线程从缓冲区中获取整数,两者都打印信息*/

#define OVER (-1)

struct prodcons buffer;

void *producer(void *data)

{

int n;

for( n=0;n1000;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;

else

printf("-----%d\n",d);

}

return NULL;

}

int main()

{

pthread_t th_p,th_c;

void *retval;

pthread_init(buffer);

pthread_create(th_p,NULL,producer,0);

pthread_create(th_c,NULL,consumer,0);

/*等待两个线程结束*/

pthread_join(th_p, retval);

pthread_join(th_c,retval);

return 0;

}

C语言多线程的操作步骤

线程创建

函数原型:intpthread_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的形参。

线程挂起:该函数的作用使得当前线程挂起,等待另一个线程返回才继续执行。也就是说当程序运行到这个地方时,程序会先停止,然后等线程id为thread的这个线程返回,然后程序才会断续执行。

函数原型:intpthread_join(pthread_tthread, void **value_ptr);

参数说明如下:thread等待退出线程的线程号;value_ptr退出线程的返回值。

返回值:若成功,则返回0;若失败,则返回错误号。

线程退出

函数原型:voidpthread_exit(void *rval_ptr);

获取当前线程id

函数原型:pthread_tpthread_self(void);

互斥锁

创建pthread_mutex_init;销毁pthread_mutex_destroy;加锁pthread_mutex_lock;解锁pthread_mutex_unlock。

条件锁

创建pthread_cond_init;销毁pthread_cond_destroy;触发pthread_cond_signal;广播pthread_cond_broadcast;等待pthread_cond_wait。