Linux学习线程阶段中关于 线程 互斥锁 条件 API的相关介绍

Linux线程介绍

进程与线程
进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位。在面向线程设计的系统中,进程本身不是基本运行单位,而是线程的容器。
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
线程有自己的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
从函数调用上来说,进程创建使用fork()操作;线程创建使用clone()操作。

使用线程的理由
进程有独立的地址空间,线程没有单独的地址空间(同一进程内的线程共享进程的地址空间)。
使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计,总的说来,一个进程的开销大约是一个线程开销的30倍左右,当然,在具体的系统上,这个数据可能会有较大的区别。
使用多线程的理由之二是线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。当然,数据的共享也带来其他一些问题,有的变量不能同时被两个线程所修改,有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击,这些正是编写多线程程序时最需要注意的地方。
数据共享带来其他的一些问题我们可以用条件变量和互斥锁来解决。

demo1,demo2,demo3讲述线程创建,退出,等待的API
demo4 线程共享内存空间
demo5 互斥锁创建及销毁,加锁及解锁
demo6 利用互斥锁让t1在等于3的时候退出(绝对退出)
demo7 死锁怎么造成的
demo8 关于创建销毁等待触发条件的API
demo9 关于动态静态初始化,生产者消费者的使用

.sh是脚本文件,chmod +x xxx.sh可以给他执行权限

pthread_create函数(线程创建)

若成功返回0,否则返回错误编号

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
thread:新创建线程的线程ID
attr:用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
start_routine:函数指针
arg:第三个参数函数传递的参数,如果需要向函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

pthread_join函数(线程等待)

成功返回0,否则返回错误编号
调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);
thread:线程ID
retval:线程返回值,对线程返回值不感兴趣,可以设置为NULL

pthread_exit函数(线程退出)

#include <pthread.h>

void pthread_exit(void *retval);
retva:无类型指针,与传给启动历程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问这个指针

pthread_self与pthread_equal函数(线程ID获取及比较)

对于线程ID比较,为了可移植操作,我们不能简单地把线程ID当作整数来处理,因为不同系统对线程ID的定义可能不一样。我们应该要用下边的pthread_equal函数

#include <pthread.h>

pthread_t pthread_self(void);
返回:调用线程的ID

int pthread_equal(pthread_t tid1, pthread_t tid2);
返回:若相等返回非0,否则返回0

pthread_mutex_init与pthread_mutex_destroy函数(创建及销毁互斥锁)

成功返回0,否则返回错误编号

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
mutex:一个指针,用pthread_mutex_t数据类型表示
attr:互斥量,只需把attr设置为NULL,用默认的属性初始化

int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex:销毁你创建的参数指针

pthread_mutex_lock与pthread_mutex_unlock函数(加锁及解锁)

成功返回0,否则返回错误编号

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex:创建的参数指针

int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex:创建的参数指针

pthread_cond_init与pthread_cond_destroy函数(创建及销毁条件变量)

成功返回0,否则返回错误编号
条件变量使用之前必须首先初始化,pthread_cond_t数据类型代表的条件变量可以用两种方式进行初始化,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,但是如果条件变量是动态分配的,可以使用pthread_cond_destroy函数对条件变量进行去除初始化。

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
cond:一个指针,用pthread_cond_t数据类型表示
attr:除非需要创建一个非默认属性的条件变量,否则attr参数可以设置为NULL。

int pthread_cond_destroy(pthread_cond_t *cond);
cond:销毁你创建的参数指针

pthread_cond_wait和pthread_cond_timedwait函数(等待)

成功返回0,否则返回错误编号

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
cond:创建的条件参数
mutex:创建的线程参数

int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
cond:创建的条件参数
mutex:创建的线程参数
timeout:指定等待的时间

pthread_cond_signal和pthread_cond_broadcast函数(触发)

成功返回0,否则返回错误编号
这两个函数可以用于通知线程条件已经满足。pthread_cond_signal函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast函数将唤醒等待该条件的所有进程。

注意一定要在改变条件状态以后再给线程发信号。

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
cond:创建的条件参数

int pthread_cond_broadcast(pthread_cond_t *cond);
cond:创建的条件参数

结合所讲的函数代码

/****************************demo1****************************/
#include <stdio.h>
#include <pthread.h>

//	int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//  void *(*start_routine) (void *), void *arg);

void *fun1(void *arg)
{
        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
}

int main()
{
        pthread_t t1;
        int num = 10;

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数是一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递的
        //参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        while(1);  //无限循环
        return 0;
}
/****************************demo2****************************/
#include <stdio.h>
#include <pthread.h>

//	int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//	void *(*start_routine) (void *), void *arg);
//	int pthread_join(pthread_t thread, void **retval);
//	void pthread_exit(void *retval);


void *fun1(void *arg)
{
        static int ret = 10;

        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,100

        pthread_exit((void *)&ret);  //调用退出,返回值是10
}

int main()
{
        int *p = NULL;
        pthread_t t1;
        int num = 100;

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递的
        //参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
        if(ret == 0){
                printf("main:create t1 success\n");
        }
        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        
        pthread_join(t1,(void **)&p);  //调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
        //第二个参数是exit返回的参数
        printf("main:t1 quit:%d\n",*p);  //打印这个返回的内容,10

//      while(1);
        return 0;
}
/****************************demo3****************************/
#include <stdio.h>
#include <pthread.h>

//	int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//  void *(*start_routine) (void *), void *arg);
//	int pthread_join(pthread_t thread, void **retval);
//	void pthread_exit(void *retval);


void *fun1(void *arg)
{
        static char *ret = "t1 is run out";

        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));    //打印传递过来的值,100
        pthread_exit((void *)ret);  //调用退出,返回值是t1 is run out
}

int main()
{
        char *p = NULL;
        pthread_t t1;
        int num = 100;

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递的
        //参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
        if(ret == 0){
                printf("main:create t1 success\n");
        }
        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        pthread_join(t1,(void **)&p);  //调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
        //第二个参数是exit返回的参数
        printf("main:t1 quit:%s\n",p);  //打印这个返回的内容,t1 is run out

//      while(1);
        return 0;
}
/****************************demo4****************************/
#include <stdio.h>
#include <pthread.h>

//	int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//  void *(*start_routine) (void *), void *arg);

int g_data = 0;

void *fun1(void *arg)
{
        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,10

        while(1){
                sleep(1);
                printf("t1: %d\n",g_data++);

                if(g_data == 3){
                        pthread_exit(NULL);

                }
        }
}

void *fun2(void *arg)
{
        printf("t2:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t2:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        
        while(1){
                sleep(1);
                printf("t2: %d\n",g_data++);
        }
}

int main()
{
        pthread_t t1;
        pthread_t t2;
        int num = 10;
		int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
		//暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递的
		//参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传>入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数
        //传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。
        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        while(1){
                sleep(1);
                printf("main: %d\n",g_data++);
        }

        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        while(1);  //无限循环
        return 0;
}
/****************************demo5****************************/
#include <stdio.h>
#include <pthread.h>

//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//              void *(*start_routine) (void *), void *arg);

//1. 创建及销毁互斥锁
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//int pthread_mutex_destroy(pthread_mutex_t mutex);

//2. 加锁及解锁
//int pthread_mutex_lock(pthread_mutex_t *mutex);
//int pthread_mutex_trylock(pthread_mutex_t *mutex);
//int pthread_mutex_unlock(pthread_mutex_t *mutex);

int g_data = 0;
pthread_mutex_t mutex;

void *fun1(void *arg)
{
        pthread_mutex_lock(&mutex);  //加锁,设一个全局变量取地址
        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);  //解锁,你加锁的地址
}
void *fun2(void *arg)
{
        pthread_mutex_lock(&mutex);  //加锁,设一个全局变量取地址
        printf("t2:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t2:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);  //解锁,你加锁的地址

}

void *fun3(void *arg)
{
        pthread_mutex_lock(&mutex);  //加锁,设一个全局变量取地址
        printf("t3:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t3:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);  //解锁,你加锁的地址

}

int main()
{
        pthread_t t1;
        pthread_t t2;
        pthread_t t3;
        int num = 10;

        pthread_mutex_init(&mutex,NULL); //创建锁,第一个参数是一个指针,在上面定义了一个全局变量,第二个参数要用默认的属性初始化
        //互斥量,只需把attr设置为NULL。

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程
        //属性,暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需
        //要向函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);

        ret = pthread_create(&t3,NULL,fun3,(void *)&num);

        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。


        pthread_join(t1,NULL);  //调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。
        //第二个参数是exit返回的参数
        pthread_join(t2,NULL);
        pthread_join(t3,NULL);

        pthread_mutex_destroy(&mutex);  //销毁锁,销毁你创建的参数指针

        //while(1);  //无限循环
        return 0;
}
/****************************demo6****************************/
#include <stdio.h>
#include <pthread.h>

//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//              void *(*start_routine) (void *), void *arg);

int g_data = 0;

pthread_mutex_t mutex;

void *fun1(void *arg)
{
        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,10

        pthread_mutex_lock(&mutex);  //加锁
        while(1){
                sleep(1);
                printf("t1: %d\n",g_data++);

                if(g_data == 3){
                        pthread_mutex_unlock(&mutex);  //解锁
                        printf("t1 quit===========================\n");
                        pthread_exit(NULL);

                }
        }
}

void *fun2(void *arg)
{
        printf("t2:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t2:arg = %d\n",*((int *)arg));  //打印传递过来的值,10

        while(1){
                sleep(1);
                printf("t2: %d\n",g_data);
                pthread_mutex_lock(&mutex);  //如果t2先获得执行权那就g_data++,运行结束后等于g_data=1,然后fun1获得执行权,
                //因为fun1的解锁放在了之后在t1等于3的时候才解锁,所以无论t2获得加锁的权利,都不可能打断t1的运行,因为t1还没有
                //解锁,所以t2会一直阻塞到t1解锁
                g_data++;
                pthread_mutex_unlock(&mutex);
                pthread_exit(NULL);
        }
}

int main()
{
        pthread_t t1;
        pthread_t t2;
        int num = 10;

        pthread_mutex_init(&mutex,NULL);

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递
        //的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);

        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        pthread_mutex_destroy(&mutex);

        //while(1);  //无限循环
        return 0;
}
/****************************demo7****************************/
#include <stdio.h>
#include <pthread.h>

//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//              void *(*start_routine) (void *), void *arg);

//1. 创建及销毁互斥锁
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
//int pthread_mutex_destroy(pthread_mutex_t *mutex);

//2. 加锁及解锁
//int pthread_mutex_lock(pthread_mutex_t *mutex);
//int pthread_mutex_trylock(pthread_mutex_t *mutex);
//int pthread_mutex_unlock(pthread_mutex_t *mutex);

int g_data = 0;
pthread_mutex_t mutex;  //造成死锁的前提是最少要两把锁
pthread_mutex_t mutex2;

void *fun1(void *arg)
{
        pthread_mutex_lock(&mutex);  
        sleep(1);
        pthread_mutex_lock(&mutex2);  //线程1想要去获取线程2的锁,而下面线程2有线程1想要获取的锁,线程2也想获取线程1的锁,
        //两个都想获取对方手里的那把锁,都不肯解锁,这样就导致了死锁
        printf("t1:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t1:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);
}

void *fun2(void *arg)
{
        pthread_mutex_lock(&mutex2);
        sleep(1);
        pthread_mutex_lock(&mutex);
        printf("t2:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t2:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);

void *fun3(void *arg)
{
        pthread_mutex_lock(&mutex);
        printf("t3:%ld create pthread success\n",(unsigned long)pthread_self());  //获得线程自身的ID。
        printf("t3:arg = %d\n",*((int *)arg));  //打印传递过来的值,10
        pthread_mutex_unlock(&mutex);

}

int main()
{
        pthread_t t1;
        pthread_t t2;
        pthread_t t3;
        int num = 10;

        pthread_mutex_init(&mutex,NULL);
        pthread_mutex_init(&mutex2,NULL);

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的
        //线程属性,暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,
        //如果需要向函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传>入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);

        ret = pthread_create(&t3,NULL,fun3,(void *)&num);

        printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。


        pthread_join(t1,NULL);    //调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返>回或者被取消。
        //第二个参数是exit返回的参数
        pthread_join(t2,NULL);
        pthread_join(t3,NULL);

        pthread_mutex_destroy(&mutex);
        pthread_mutex_destroy(&mutex2);

        //while(1);  //无限循环
        return 0;
}
/****************************demo8****************************/
#include <stdio.h>
#include <pthread.h>

//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//              void *(*start_routine) (void *), void *arg);

int g_data = 0;

pthread_mutex_t mutex;
pthread_cond_t cond;

void *fun1(void *arg)
{
        while(1){
                pthread_cond_wait(&cond,&mutex);

                printf("t1 run===========================\n");
                printf("t1: %d\n",g_data);
                g_data=0;

                sleep(1);
        }
}

void *fun2(void *arg)
{
        while(1){
                sleep(1);
                printf("t2: %d\n",g_data);
                pthread_mutex_lock(&mutex);
                g_data++;
                if(g_data == 3){
                        pthread_cond_signal(&cond);
                }
                pthread_mutex_unlock(&mutex);
        }
}

int main()
{
        pthread_t t1;
        pthread_t t2;
        int num = 10;

        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&cond,NULL);

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递
        //的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传>入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);

//      printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        pthread_join(t1,NULL);
        pthread_join(t2,NULL);

        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);

        return 0;
}     
/****************************demo9****************************/
#include <stdio.h>
#include <pthread.h>

//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//              void *(*start_routine) (void *), void *arg);

int g_data = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;  //静态初始化
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;  //静态初始化

void *fun1(void *arg)
{
        while(1){
                pthread_cond_wait(&cond,&mutex);

                printf("t1 run===========================\n");
                printf("t1: %d\n",g_data);
                g_data=0;

                sleep(1);
        }
}

void *fun2(void *arg)
{
        while(1){
                sleep(1);
                printf("t2: %d\n",g_data);
                pthread_mutex_lock(&mutex);
                g_data++;
                if(g_data == 3){
                        pthread_cond_signal(&cond);
                }
                pthread_mutex_unlock(&mutex);
        }
}

int main()
{
        pthread_t t1;
        pthread_t t2;
        int num = 10;

//      pthread_mutex_init(&mutex,NULL);  //动态初始化
//      pthread_cond_init(&cond,NULL);  //动态初始化

        int ret = pthread_create(&t1,NULL,fun1,(void *)&num);  //t1被设置为新创建线程的线程ID。attr参数用于定制各种不同的线程属性,
        //暂可以把它设置为NULL,以创建默认属性的线程。第三个参数时一个函数指针,第四个参数是第三个参数函数传递的参数,如果需要向函数传递
        //的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。

        ret = pthread_create(&t2,NULL,fun2,(void *)&num);

//      printf("main:%ld\n",(unsigned long)pthread_self());  //获得线程自身的ID。

        pthread_join(t1,NULL);
        pthread_join(t2,NULL);

        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);

        return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值