目录
3、创建及销毁互斥锁pthread_mutex_init()、pthread_mutex_destroy()
4、加锁及解锁pthread_mutex_lock()、pthread_mutex_unlock()
3、销毁条件变量pthread_cond_destroy()
线程和进程的区别:
进程是程序执行时的一个实例,是担当分配系统资源(CPU时间、内存等)的基本单位,还是线程的容器。
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
第一种方法:
一个进程在运行的时候,要给他分配内存,要维护它的数据段和代码段以及堆栈等等,而线程是跟进程共享这些东西,开辟多个线程不会分配新的内存,和进程相比,它是一种非常"节俭"的多任务操作方式。
第二种方法:
1.根本区别:进程是操作系统进行资源分配的最小单元,线程是操作系统进行运算调度的最小单元。
2.从属关系不同:进程中包含了线程,线程属于进程。
3.开销不同:进程的创建、销毁和切换的开销都远大于线程。
4.拥有资源不同:每个进程有自己的内存和资源,一个进程中的线程会共享这些内存和资源。
5.控制和影响能力不同:子进程无法影响父进程,而子线程可以影响父线程,如果主线程发生异常会影响其所在进程和子线程。
6.CPU利用率不同:进程的CPU利用率较低,因为上下文切换开销较大,而线程的CPU的利用率较高,上下文的切换速度快。
7.操纵者不同:进程的操纵者一般是操作系统,线程的操纵者一般是编程人员。
Linux线程开发常用API
一、线程相关API
1、线程的创建pthread_create()
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_t *thread: pthread是一个指针参数,传出线程ID
const pthread_attr_t *attr: 用于指定线程属性,传入NULL表示使用默认属性
void *(*start_routine) (void *): 是个函数指针,是线程的主控函数
void *arg: 是第三个函数的参数,要强制转换成泛型(void*)然后进行值
传递即可,不能传递地址
返回值:若成功返回0,否则返回错误编号
2、线程的等待pthread_join()
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
pthread_t thread: thread是我们要等待退出的线程的线程ID
void **retval: retval是传出参数,用于获取线程的退出值,即,pthread_exit里的那个参数
在使用该函数时要注意retval参数:
(1) 一定要用void**强制转换为泛型指针
(2)该函数是将pthread_exit里的退出值 复制到 retval所指向的位置。
(3)该参数可以置为NULL,表示不需要获取线程退出值。
3、线程的退出pthread_exit()
#include <pthread.h>
void pthread_exit(void *retval);
void *retval: retval表示线程的退出值,我们必须将该参数强转为泛型void*
举例,实现线程创建退出
#include<stdio.h>
#include<pthread.h>
void *func1(void * arg){
// static int ret=10;
static char *ret="t1 is run out";
printf("t1: %ld thread is creat\n ",(unsigned long)pthread_self());
printf("t1: param is %d\n",*((int *)arg));
pthread_exit((void *)ret);
}
int main(){
int param=100;
int ret;
//int *pret=NULL;//传一个整形参数给phread_join
char *pret=NULL;//传一个字符串参数给phread_join
pthread_t t1;
ret=pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret == 0){
printf("main:thread craet success\n");
}
printf("main: %ld\n ",(unsigned long)pthread_self());
// while(1);
pthread_join(t1, (void**)&pret);
// printf("main t1 quit %d\n",pret);
printf("main t1 quit %s\n",pret);
return 0;
}
4、线程ID获取pthread_self()
#include <pthread.h>
pthread_t pthread_self(void);
//返回值:调用线程的ID
二、互斥锁相关API
1、什么是互斥锁
互斥锁也称为互斥量,对共享资源进行锁定,保证同一时刻只能有一个线程去操作。对互斥量进行加锁后,任何其他试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥锁。
2、创建互斥量
pthread_mutex_t mutex; //此创建的互斥量为全局变量
3、创建及销毁互斥锁pthread_mutex_init()、pthread_mutex_destroy()
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
//返回值:若成功返回0,否则返回错误编号
4、加锁及解锁pthread_mutex_lock()、pthread_mutex_unlock()
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//返回值:若成功返回0,否则返回错误编号
举例:如何创建一个互斥锁代码实现
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex;
void *func1(void * arg){
int i;
pthread_mutex_lock(&mutex);//上锁
for(i=0;i<5;i++){
printf("t1: %ld thread is creat\n",(unsigned long)pthread_self());
printf("t1: param is %d\n",*((int *)arg));
}
pthread_mutex_unlock(&mutex);//解锁
};
void *func2(void * arg){
printf("t2: %ld thread is creat\n",(unsigned long)pthread_self());
printf("t2: param is %d\n",*((int *)arg));
};
int main(){
int param=100;
int ret;
char *pret=NULL;
pthread_t t1;
pthread_t t2;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init(&mutex,NULL);//创建互斥锁
ret=pthread_create(&t1,NULL,func1,(void *)¶m);
ret=pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret == 0){
printf("main:thread craet success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex);//销毁锁
return 0;
}
举例,互斥锁限制共享资源
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
int g_data=0;
pthread_mutex_t mutex1;
void *func1(void * arg){
int i;
pthread_mutex_lock(&mutex1);//上锁
while(1){
g_data++;
printf("t1:g_data is %d\n",g_data);
if(g_data==3){
printf("g_data=3 =============\n");
exit(0);
}
sleep(1);
// pthread_mutex_unlock(&mutex1);//解锁
}
};
void *func2(void * arg){
while(1){
pthread_mutex_lock(&mutex1);
g_data++;
printf("t2 g_data is %d\n",g_data);
pthread_mutex_unlock(&mutex1);
sleep(1);
}
};
int main(){
int param=100;
int ret1;
int ret2;
char *pret=NULL;
pthread_t t1;
pthread_t t2;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init(&mutex1,NULL);//创建互斥锁
ret1=pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret1 == 0){
printf("main:thread craet success\n");
}
ret1=pthread_create(&t2,NULL,func2,(void *)¶m);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex1);//销毁锁
return 0;
}
5、死锁
首先有两个线程,也有两把锁。线程一已经上锁A的没有解锁情况下还想去上锁B,同时线程二也跟线程一一样,要上锁A,这样线程一和线程二都想要对方的锁,谁也不让着谁,这样就会造成死锁。
举例,死锁代码
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
void *func1(void * arg){
int i;
pthread_mutex_lock(&mutex1);//上锁1
sleep(1);
pthread_mutex_lock(&mutex2);//上锁2
for(i=0;i<5;i++){
printf("t1: %ld thread is creat\n",(unsigned long)pthread_self());
printf("t1: param is %d\n",*((int *)arg));
}
pthread_mutex_unlock(&mutex1);//解锁
};
void *func2(void * arg){
pthread_mutex_lock(&mutex2);//上锁2
sleep(1);
pthread_mutex_lock(&mutex1);//上锁1
printf("t2: %ld thread is creat\n",(unsigned long)pthread_self());
printf("t2: param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex2);
};
int main(){
int param=100;
int ret1;
int ret2;
char *pret=NULL;
pthread_t t1;
pthread_t t2;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init(&mutex1,NULL);//创建互斥锁
pthread_mutex_init(&mutex2,NULL);//创建互斥锁
ret1=pthread_create(&t1,NULL,func1,(void *)¶m);
if(ret1 == 0){
printf("main:thread craet success\n");
}
ret2=pthread_create(&t2,NULL,func2,(void *)¶m);
if(ret2 == 0){
printf("main:thread craet success\n");
}
printf("main: %ld\n",(unsigned long)pthread_self());
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex1);//销毁锁
pthread_mutex_destroy(&mutex2);//销毁锁
return 0;
}
三、条件变量相关API
条件变量定义
条件变量是线程另一可用的同步机制。条件变量给多个线程提供了一个会合的场所。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。
1、定义条件变量
pthread_cond_t cond;
2、初始化条件变量pthread_cond_init()
#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_t *restrict cond: 条件变量的地址
const pthread_condattr_t *restrict attr: 条件变量的属性,默认写NULL
// 返回:若成功返回0,否则返回错误编号
3、销毁条件变量pthread_cond_destroy()
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t cond);
pthread_cond_t cond: 条件变量的地址
// 返回:若成功返回0,否则返回错误编号
4、等待条件变量pthread_cond_wait()
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
pthread_cond_t *restrict cond: 条件变量的地址
pthread_mutex_t *restrict mutex: 互斥锁的地址
// 返回:若成功返回0,否则返回错误编号
5、唤醒条件变量pthread_cond_signal()
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond); 函数将唤醒等待该条件的某个线程
int pthread_cond_broadcast(pthread_cond_t cond); 函数将唤醒等待该条件的所有进程
pthread_cond_t cond: 条件变量的地址
// 返回:若成功返回0,否则返回错误编号
举例:条件变量实战
#include<stdio.h>
#include<pthread.h>
#include <stdlib.h>
int g_data=0;
pthread_cond_t cond;
pthread_mutex_t mutex1;
void *func1(void * arg){
static int cnt=0;
while(1){
pthread_cond_wait(&cond,&mutex1);//等待触发条件变量
printf("t1 is run ==================\n");
g_data=0;//置零,线程二重复调用
if(cnt++ == 10){
exit(-1);
}
}
};
void *func2(void * arg){
while(1){
pthread_mutex_lock(&mutex1);
printf("t2 g_data is %d\n",g_data);
g_data++;
if(g_data==3){
pthread_cond_signal(&cond);//触发条件变量
}
pthread_mutex_unlock(&mutex1);
sleep(1);
}
};
int main(){
int param=100;
int ret1;
int ret2;
char *pret=NULL;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex1,NULL);//创建互斥锁
ret1=pthread_create(&t1,NULL,func1,(void *)¶m);
ret1=pthread_create(&t2,NULL,func2,(void *)¶m);
pthread_cond_init(&cond,NULL);//初始化条件变量
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_mutex_destroy(&mutex1);//销毁锁
pthread_cond_destroy(&cond);//销毁条件变量
return 0;
}
6、静态定义与动态定义条件变量
动态初始化:
pthread_mutex_t mutex; //dynamic init
pthread_cond_t cond; //dynamic init
主函数中必须:
pthread_mutex_init(&mutex, NULL); //dynamic init
pthread_cond_init(&cond, NULL); //dynamic init
使用宏进行初始化(静态初始化):
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // static init
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; // static init