Unix高级编程:线程基础、线程的创建、退出、分离、汇合、同步问题
2017-01-15 22:57
411 查看
一、线程的基础知识
进程和程序的区别
进程和线程的区别:
"线程,是执行的基本单位,线程共享进程的资源"。
(1条线程就是1条执行的基本单位,每个线程有自己独立的栈帧)
进程,是资源分配的基本单位,调度的单位。
进程有自己的pid,线程也有自己的id,称为"tid"。
"一个进程里可以有多个线程"。
每个进程都至少有一个线程,这个线程是进程的主线程。
需要"多条执行路线"时,使用多进程的话,进程间切换资源开销比较大,原因是需要复制PCB。"使用线程不需要复制PCB,属于进程内的切换,资源开销小"。
二、线程的创建
"pthread_create"(3)
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with "-pthread". /** 编译加上该库 -lpthread **/
功能:创建一个新的线程
参数:
"thread" 将 tid 存放在该参数的变量空间里
"attr" 取 NULL 采用默认的属性
"start_routine" (函数访问方式,返回值void *,参数void *)
新线程执行的函数
"arg" 是start_routine函数的唯一的参数
返回值:
成功 - 返回 0
失败 - 返回一个错误号,thread未定义。
/** 举例验证:
在进程中创建线程,pthread_create.c **/
#include <stdio.h>
#include <pthread.h>
//线程的执行函数
void *handle(void *arg) {
printf("arg: %s\n", (char *)arg);
printf("pid: %d \t tid: %lu\n", getpid(), pthread_self());
//两次的pid一样说明是一样
return arg; //return (void *)1; 或者 return NULL;
}
int main(void) {
pthread_t tid;
//创建一个新的线程
pthread_create(&tid, NULL, handle, "new");
sleep(1);
handle("main"); //handle的主线程
return 0;
}
gcc pthread_create.c -lpthread
查看线程自己的tid:
"pthread_self"(3)
#include <pthread.h>
pthread_t pthread_self(void);
功能:获取线程自己的id,即tid (unsigned long int) "%lu"
参数:void
返回值:
总是成功 - 返回线程的id
三、线程的退出
1. 线程里不能使用使用"exit"(3)退出,可以使用"return"退出
千万不要使用return返回 <局部变量> 的地址
2. 线程里还可以使用"pthread_exit"(3)退出线程,只是退出当前线程。
3. 线程里还可以使用"pthread_cancel"(3)终止某个线程
"pthread_exit"(3)
#include <pthread.h>
void pthread_exit(void *retval);
功能:终止线程
参数:"retval" 这个值被调用的pthread_join的线程使用
返回值:void
注意:pthread_exit的"参数不能使用局部变量的地址",局部变量栈里。
"pthread_cancel"(3)
#include <pthread.h>
int pthread_cancel(pthread_t thread);
功能:给一个线程发送终止请求
参数:"thread" 指定接收终止请求的线程
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
四、线程的分离和汇总
线程的"分离":
"pthread_detach"(3)
#include <pthread.h>
int pthread_detach(pthread_t thread);
功能:分离一个线程。一个线程终止,资源自动回收,不需要其他线程参与
参数:"thread" 要分离的线程tid
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
线程的"汇总":
"pthread_join"(3)
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
功能:等待线程终止,回收线程资源
参数:
"thread" 指定要等待的线程的tid
"retval" 存放thread指定的线程的退出状态码
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
/** 举例验证:
使用各种线程的退出方式,然后回收线程资源 pthread_join.c **/
#include <stdio.h>
#include <pthread.h>
void *handle1(void *arg) {
printf("thread %s running...\n", (char *)arg); //new
return (void *)1;
}
void *handle2(void *arg) {
printf("thread %s running...\n", (char *)arg);//second
pthread_exit( (void *)2 );
}
void *handle3(void *arg) {
while(1) {
printf("thread %s running...\n", (char *)arg);
sleep(1);
}
}
int main(void) {
pthread_t tid;
void *ret;
//创建一个线程
pthread_create(&tid, NULL, handle1, "new"); //新线程先执行
//等待线程汇合
pthread_join(tid, &ret); //void **retval
printf("new exit code %d\n", (int)ret); //1
//创建第二个线程
pthread_create(&tid, NULL, handle2, "second");
pthread_join(tid, &ret);
printf("second exit code %d\n", (int)ret);//2
//创建第三个线程
pthread_create(&tid, NULL, handle3, "third");
//给线程发送终止信息
pthread_cancel(tid);
//等待线程汇合
pthread_join(tid, &ret);
printf("third exit code %d\n", (int)ret);
//创建第四个线程
pthread_create(&tid, NULL, handle2, "fourth");
//分离线程,资源自动回收
pthread_detach(tid);
handle1("main"); //新线程执行完,主线程执行
return 0;
}
五、线程的同步
线程创建完毕,多线程和是异步的。异步的线程同时访问临界资源,这时候会出现错误。为了解决这些错误,引进了线程的同步。
/** 举例说明:
多线程异步访问临界资源,出现问题的情况。any_thread.c **/
#include <stdio.h>
#include <pthread.h>
#define NLOOP 5000
int counter;
void *doit(void *arg) {
int val;
for(int i = 0; i < NLOOP; i++) {
val = counter;
printf("%lu : %d\n", pthread_self(), val+1);//每次5000多
counter = val+1;
}
return NULL;
}
int main(void) {
pthread_t tidA, tidB;
//创建两个线程
pthread_create(&tidA, NULL, doit, NULL);
pthread_create(&tidB, NULL, doit, NULL);
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
"mutex锁"
线程对临界资源访问的时候,上一把锁,上锁成功,才可以访问;上锁不成功,不能访问。
线程访问临界资源的时候,首先要获取一把锁。
使用mutex锁需要使用下列函数:
"pthread_mutex_init"(3)
"pthread_mutex_lock"(3)
"pthread_mutex_trylock"(3)
"pthread_mutex_unlock"(3)
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //初始化锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
功能:初始化mutex锁
参数:
"mutex" 要初始化的mutex锁
"mutexattr" NULL 缺省
返回值:
成功 - 总是返回 0
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:加锁,如果这把锁没有锁上,加锁并改成自己拥有且立即返回;
如果这把锁由其它线程加锁,那么当前线程就挂起等待,直到该锁被解开,当前线程获取这把锁。
参数:"mutex" 指定要上锁的锁。
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_trylock(pthread_mutex_t *mutex);
功能:尝试加锁,如果锁没有被另外的线程使用,立即加锁并返回;
如果被其他线程加锁,立即返回,并将错误码置为 EBUSY 。
参数:"mutex" 尝试加锁的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解开锁,锁原来是锁着的,还是当前线程所拥有的锁。
参数:"mutex" 要解开的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁锁,并释放mutex持有的资源
参数:"mutex" 要销毁的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
/** 举例验证:
使用mutex锁解决多线程同步会导致错误的问题。mutex.c**/
#include <stdio.h>
#include <pthread.h>
#define NLOOP 5000
//初始化一把mutex锁,全局初始化锁
pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
int counter;
void *doit(void *arg) {
int val;
for(int i = 0; i < NLOOP; i++) {
//加锁,在开始访问全局变量时
pthread_mutex_lock(&fmutex);
val = counter;
printf("%lu : %d\n", pthread_self(), val+1);//每次5000多
counter = val+1;
//解锁,在结束访问完全局变量时
pthread_mutex_unlock(&fmutex);
}
return NULL;
}
int main(void) {
pthread_t tidA, tidB;
//创建两个线程
pthread_create(&tidA, NULL, doit, NULL);
pthread_create(&tidB, NULL, doit, NULL);
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
//销毁mutex锁
pthread_mutex_destroy(&fmutex);
return 0;
}
"条件变量"
线程间同步还有这样一种情况,线程A需要等待某个条件成立才能继续往下执行。现在这个条件不成里,线程A就阻塞等待;而线程B在执行过程中使这个条件成立,就唤醒了线程A,线程A继续执行。这个条件,就称为"条件变量"。
使用条件变量,需要使用以下函数:
"pthread_cond_init"(3)
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
功能:初始化一个条件变量
参数:
"cond" 要初始化的条件变量
"cond_attr" NULL,默认属性
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_signal(pthread_cond_t *cond);
功能:通知在cond条件上等待的线程,从中任选一个开始执行
参数:"cond" 指定了条件
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:唤醒了所有在cond条件上等待的线程
参数:"cond" 等待的条件
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
功能:1. 解开mutex锁;2. 阻塞等待;3. 当条件成立的时候被唤醒,重新加锁
参数:
"cond" 阻塞等待的条件
"mutex" 被解开的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
功能:类似于pthread_cond_wait,但是有等待周期
参数:
"cond" 阻塞等待的条件
"mutex" 被解开的锁
"abstime" 指定了等待周期的时间
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁一个变量,释放资源
参数:"cond" 要销毁的条件变量
返回值:
成功 - 返回 0
失败 - 返回错误码
/** 举例验证:
使用条件变量实现生产者和消费者的例子。
生产者生产一个结构体串在链表的头上,而消费者从头部取走一个结构体消费。 consumer.c **/
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
typedef struct msg{
int num;
struct msg *next;
}msg_t; //共享临界资源:链表
msg_t *head = NULL;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void *arg) {
msg_t *p;
for(;;) {
//先加锁,开始操作时
pthread_mutex_lock(&mutex);
if(head == NULL) { //if == while
//解锁->等待条件成立->再加上锁
pthread_cond_wait(&cond, &mutex);
}
//代表链表非空,才能操作
p = head;
head = p->next;
//再解锁,操作完时
pthread_mutex_unlock(&mutex);
printf("c %d\n", p->num);
free(p);
p = NULL;
sleep(rand() % 5);
}
}
void *producer(void *arg) {
msg_t *new;
for(;;) {
new = (msg_t *)malloc(sizeof(msg_t));
new->num = rand() % 1000 + 1;
printf("p %d\n", new->num);
//加锁
pthread_mutex_lock(&mutex);
//链表操作,增加链表中的数据
new->next = head;
head = new;
//解锁
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);//通知cond上等待的线程,任选执行
sleep(rand() % 5);
}
return ;
}
int main(void) {
srand(time(NULL));
pthread_t pid, cid;
//创建两个线程,1个用于生产,1个用于消费
pthread_create(&pid, NULL, producer, NULL); //生产者
pthread_create(&cid, NULL, consumer, NULL); //消费者
//join等待两个线程汇合,对结束状态不需要关心,所以取NULL
pthread_join(cid, NULL);
pthread_join(pid, NULL);
return 0;
}
进程和程序的区别
进程和线程的区别:
"线程,是执行的基本单位,线程共享进程的资源"。
(1条线程就是1条执行的基本单位,每个线程有自己独立的栈帧)
进程,是资源分配的基本单位,调度的单位。
进程有自己的pid,线程也有自己的id,称为"tid"。
"一个进程里可以有多个线程"。
每个进程都至少有一个线程,这个线程是进程的主线程。
需要"多条执行路线"时,使用多进程的话,进程间切换资源开销比较大,原因是需要复制PCB。"使用线程不需要复制PCB,属于进程内的切换,资源开销小"。
二、线程的创建
"pthread_create"(3)
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with "-pthread". /** 编译加上该库 -lpthread **/
功能:创建一个新的线程
参数:
"thread" 将 tid 存放在该参数的变量空间里
"attr" 取 NULL 采用默认的属性
"start_routine" (函数访问方式,返回值void *,参数void *)
新线程执行的函数
"arg" 是start_routine函数的唯一的参数
返回值:
成功 - 返回 0
失败 - 返回一个错误号,thread未定义。
/** 举例验证:
在进程中创建线程,pthread_create.c **/
#include <stdio.h>
#include <pthread.h>
//线程的执行函数
void *handle(void *arg) {
printf("arg: %s\n", (char *)arg);
printf("pid: %d \t tid: %lu\n", getpid(), pthread_self());
//两次的pid一样说明是一样
return arg; //return (void *)1; 或者 return NULL;
}
int main(void) {
pthread_t tid;
//创建一个新的线程
pthread_create(&tid, NULL, handle, "new");
sleep(1);
handle("main"); //handle的主线程
return 0;
}
gcc pthread_create.c -lpthread
查看线程自己的tid:
"pthread_self"(3)
#include <pthread.h>
pthread_t pthread_self(void);
功能:获取线程自己的id,即tid (unsigned long int) "%lu"
参数:void
返回值:
总是成功 - 返回线程的id
三、线程的退出
1. 线程里不能使用使用"exit"(3)退出,可以使用"return"退出
千万不要使用return返回 <局部变量> 的地址
2. 线程里还可以使用"pthread_exit"(3)退出线程,只是退出当前线程。
3. 线程里还可以使用"pthread_cancel"(3)终止某个线程
"pthread_exit"(3)
#include <pthread.h>
void pthread_exit(void *retval);
功能:终止线程
参数:"retval" 这个值被调用的pthread_join的线程使用
返回值:void
注意:pthread_exit的"参数不能使用局部变量的地址",局部变量栈里。
"pthread_cancel"(3)
#include <pthread.h>
int pthread_cancel(pthread_t thread);
功能:给一个线程发送终止请求
参数:"thread" 指定接收终止请求的线程
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
四、线程的分离和汇总
线程的"分离":
"pthread_detach"(3)
#include <pthread.h>
int pthread_detach(pthread_t thread);
功能:分离一个线程。一个线程终止,资源自动回收,不需要其他线程参与
参数:"thread" 要分离的线程tid
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
线程的"汇总":
"pthread_join"(3)
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
功能:等待线程终止,回收线程资源
参数:
"thread" 指定要等待的线程的tid
"retval" 存放thread指定的线程的退出状态码
返回值:
成功 - 返回 0
失败 - 返回非 0 错误号
/** 举例验证:
使用各种线程的退出方式,然后回收线程资源 pthread_join.c **/
#include <stdio.h>
#include <pthread.h>
void *handle1(void *arg) {
printf("thread %s running...\n", (char *)arg); //new
return (void *)1;
}
void *handle2(void *arg) {
printf("thread %s running...\n", (char *)arg);//second
pthread_exit( (void *)2 );
}
void *handle3(void *arg) {
while(1) {
printf("thread %s running...\n", (char *)arg);
sleep(1);
}
}
int main(void) {
pthread_t tid;
void *ret;
//创建一个线程
pthread_create(&tid, NULL, handle1, "new"); //新线程先执行
//等待线程汇合
pthread_join(tid, &ret); //void **retval
printf("new exit code %d\n", (int)ret); //1
//创建第二个线程
pthread_create(&tid, NULL, handle2, "second");
pthread_join(tid, &ret);
printf("second exit code %d\n", (int)ret);//2
//创建第三个线程
pthread_create(&tid, NULL, handle3, "third");
//给线程发送终止信息
pthread_cancel(tid);
//等待线程汇合
pthread_join(tid, &ret);
printf("third exit code %d\n", (int)ret);
//创建第四个线程
pthread_create(&tid, NULL, handle2, "fourth");
//分离线程,资源自动回收
pthread_detach(tid);
handle1("main"); //新线程执行完,主线程执行
return 0;
}
五、线程的同步
线程创建完毕,多线程和是异步的。异步的线程同时访问临界资源,这时候会出现错误。为了解决这些错误,引进了线程的同步。
/** 举例说明:
多线程异步访问临界资源,出现问题的情况。any_thread.c **/
#include <stdio.h>
#include <pthread.h>
#define NLOOP 5000
int counter;
void *doit(void *arg) {
int val;
for(int i = 0; i < NLOOP; i++) {
val = counter;
printf("%lu : %d\n", pthread_self(), val+1);//每次5000多
counter = val+1;
}
return NULL;
}
int main(void) {
pthread_t tidA, tidB;
//创建两个线程
pthread_create(&tidA, NULL, doit, NULL);
pthread_create(&tidB, NULL, doit, NULL);
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
return 0;
}
"mutex锁"
线程对临界资源访问的时候,上一把锁,上锁成功,才可以访问;上锁不成功,不能访问。
线程访问临界资源的时候,首先要获取一把锁。
使用mutex锁需要使用下列函数:
"pthread_mutex_init"(3)
"pthread_mutex_lock"(3)
"pthread_mutex_trylock"(3)
"pthread_mutex_unlock"(3)
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //初始化锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
功能:初始化mutex锁
参数:
"mutex" 要初始化的mutex锁
"mutexattr" NULL 缺省
返回值:
成功 - 总是返回 0
int pthread_mutex_lock(pthread_mutex_t *mutex);
功能:加锁,如果这把锁没有锁上,加锁并改成自己拥有且立即返回;
如果这把锁由其它线程加锁,那么当前线程就挂起等待,直到该锁被解开,当前线程获取这把锁。
参数:"mutex" 指定要上锁的锁。
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_trylock(pthread_mutex_t *mutex);
功能:尝试加锁,如果锁没有被另外的线程使用,立即加锁并返回;
如果被其他线程加锁,立即返回,并将错误码置为 EBUSY 。
参数:"mutex" 尝试加锁的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_unlock(pthread_mutex_t *mutex);
功能:解开锁,锁原来是锁着的,还是当前线程所拥有的锁。
参数:"mutex" 要解开的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_mutex_destroy(pthread_mutex_t *mutex);
功能:销毁锁,并释放mutex持有的资源
参数:"mutex" 要销毁的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
/** 举例验证:
使用mutex锁解决多线程同步会导致错误的问题。mutex.c**/
#include <stdio.h>
#include <pthread.h>
#define NLOOP 5000
//初始化一把mutex锁,全局初始化锁
pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
int counter;
void *doit(void *arg) {
int val;
for(int i = 0; i < NLOOP; i++) {
//加锁,在开始访问全局变量时
pthread_mutex_lock(&fmutex);
val = counter;
printf("%lu : %d\n", pthread_self(), val+1);//每次5000多
counter = val+1;
//解锁,在结束访问完全局变量时
pthread_mutex_unlock(&fmutex);
}
return NULL;
}
int main(void) {
pthread_t tidA, tidB;
//创建两个线程
pthread_create(&tidA, NULL, doit, NULL);
pthread_create(&tidB, NULL, doit, NULL);
pthread_join(tidA, NULL);
pthread_join(tidB, NULL);
//销毁mutex锁
pthread_mutex_destroy(&fmutex);
return 0;
}
"条件变量"
线程间同步还有这样一种情况,线程A需要等待某个条件成立才能继续往下执行。现在这个条件不成里,线程A就阻塞等待;而线程B在执行过程中使这个条件成立,就唤醒了线程A,线程A继续执行。这个条件,就称为"条件变量"。
使用条件变量,需要使用以下函数:
"pthread_cond_init"(3)
#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
功能:初始化一个条件变量
参数:
"cond" 要初始化的条件变量
"cond_attr" NULL,默认属性
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_signal(pthread_cond_t *cond);
功能:通知在cond条件上等待的线程,从中任选一个开始执行
参数:"cond" 指定了条件
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_broadcast(pthread_cond_t *cond);
功能:唤醒了所有在cond条件上等待的线程
参数:"cond" 等待的条件
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
功能:1. 解开mutex锁;2. 阻塞等待;3. 当条件成立的时候被唤醒,重新加锁
参数:
"cond" 阻塞等待的条件
"mutex" 被解开的锁
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
功能:类似于pthread_cond_wait,但是有等待周期
参数:
"cond" 阻塞等待的条件
"mutex" 被解开的锁
"abstime" 指定了等待周期的时间
返回值:
成功 - 返回 0
失败 - 返回错误码
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁一个变量,释放资源
参数:"cond" 要销毁的条件变量
返回值:
成功 - 返回 0
失败 - 返回错误码
/** 举例验证:
使用条件变量实现生产者和消费者的例子。
生产者生产一个结构体串在链表的头上,而消费者从头部取走一个结构体消费。 consumer.c **/
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
typedef struct msg{
int num;
struct msg *next;
}msg_t; //共享临界资源:链表
msg_t *head = NULL;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void *arg) {
msg_t *p;
for(;;) {
//先加锁,开始操作时
pthread_mutex_lock(&mutex);
if(head == NULL) { //if == while
//解锁->等待条件成立->再加上锁
pthread_cond_wait(&cond, &mutex);
}
//代表链表非空,才能操作
p = head;
head = p->next;
//再解锁,操作完时
pthread_mutex_unlock(&mutex);
printf("c %d\n", p->num);
free(p);
p = NULL;
sleep(rand() % 5);
}
}
void *producer(void *arg) {
msg_t *new;
for(;;) {
new = (msg_t *)malloc(sizeof(msg_t));
new->num = rand() % 1000 + 1;
printf("p %d\n", new->num);
//加锁
pthread_mutex_lock(&mutex);
//链表操作,增加链表中的数据
new->next = head;
head = new;
//解锁
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);//通知cond上等待的线程,任选执行
sleep(rand() % 5);
}
return ;
}
int main(void) {
srand(time(NULL));
pthread_t pid, cid;
//创建两个线程,1个用于生产,1个用于消费
pthread_create(&pid, NULL, producer, NULL); //生产者
pthread_create(&cid, NULL, consumer, NULL); //消费者
//join等待两个线程汇合,对结束状态不需要关心,所以取NULL
pthread_join(cid, NULL);
pthread_join(pid, NULL);
return 0;
}
相关文章推荐
- UNIX环境高级编程学习之第十一章线程-线程的创建、退出、等待、取消、分离
- Unix 环境高级编程---线程创建、同步、
- UNIX环境高级编程学习之第十二章线程控制-以分离状态创建线程
- UNIX环境高级编程——主线程与子线程的退出关系
- 【C语言】【unix c】线程的退出,汇合,分离
- UNIX高级环境编程笔记线程间同步
- UNIX环境高级编程——主线程与子线程的退出关系
- UNIX环境高级编程——主线程与子线程的退出关系
- UNIX环境高级编程——线程属性之分离属性
- 多线程编程1 --线程创建,退出,等待,分离
- unix 环境高级编程 线程一 创建
- UNIX环境高级编程之创建进程与线程
- UNIX环境高级编程——线程属性之分离属性
- UNIX环境高级编程——主线程与子线程的退出关系
- UNIX环境高级编程——线程属性之分离属性
- <转>unix环境高级编程中代码运行问题解决
- 多线程 读写锁 实例--同步操作双向链表(unix环境高级编程)
- Linux/Unix 编程中 POSIX 函数的线程安全问题
- 多线程编程基础(线程创建)
- Unix线程基础编程pthread