一、进程与线程的区别(面试会问)
- 进程在创建时,会建立很多的数据表来维护我们的代码段。也就是为进程分配所需要的内存,与线程相比就显得很“大方”——开销大。而进程只是线程的一个容器,“寄生”于进程。
- 进程拥有独立的地址空间,数据不共享。如果在进程间传递数据就需要用到进程间通信,调用许多的API来实现数据的传递;而线程是共享数据空间,在进行数据交换的时候就显得十分的方便。
二、线程
1.创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
2.线程退出
void pthread_exit(void *retval);
3.线程等待
int pthread_join(pthread_t thread, void **retval);
4.实例代码
创建两个线程:
#include<stdio.h>
#include<pthread.h>
void* func(void* arg)
{
static int ret=10;
printf("func:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func:%d\n",*((int*)arg));
pthread_exit((void*)&ret);
}
void* func1(void* arg)
{
static int ret=10;
printf("func1:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func1:%d\n",*((int*)arg));
pthread_exit((void*)&ret);
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
pthread_t thread;
pthread_t thread1;
int ret;
int ret1;
int arg=100;
int* pret;
int* pret1;
ret=pthread_create(&thread,NULL,&func,(void*)&arg);
if(ret!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,(void**)&pret);
printf("main:ret %d\n",*pret);
printf("\n");
ret1=pthread_create(&thread1,NULL,&func1,(void*)&arg);
if(ret1!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,(void**)&pret1);//二级指针指向ret的值
printf("main:ret1 %d\n",*pret1);
return 0;
}
三、互斥锁(线程间通信)
1.初始化互斥锁
(1).互斥锁的动态初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
mutex:互斥锁
attr:互斥锁属性,NULL表示为默认属性
(2).互斥锁静态初始化
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
2.销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
3.加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
4.解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
5.示例代码:
#include<stdio.h>
#include<pthread.h>
pthread_mutex_t mutex;
void* func(void* arg)
{
pthread_mutex_lock(&mutex);
static int ret=10;
printf("func:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func:%d\n",*((int*)arg));
pthread_mutex_unlock(&mutex);
pthread_exit((void*)&ret);
}
void* func1(void* arg)
{
pthread_mutex_lock(&mutex);
static int ret=10;
printf("func1:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func1:%d\n",*((int*)arg));
pthread_mutex_unlock(&mutex);
pthread_exit((void*)&ret);
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
pthread_t thread;
pthread_t thread1;
int ret;
int ret1;
int arg=100;
int* pret;
int* pret1;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init(&mutex,NULL);//before create pthread
ret=pthread_create(&thread,NULL,&func,(void*)&arg);
if(ret!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,(void**)&pret);
printf("main:ret %d\n",*pret);
printf("\n");
ret1=pthread_create(&thread1,NULL,&func1,(void*)&arg);
if(ret1!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,(void**)&pret1);
printf("main:ret1 %d\n",*pret1);
return 0;
}
使用互斥锁对临界资源的访问
#include<stdio.h>
#include<pthread.h>
int data=0;//临界资源
pthread_mutex_t mutex;
void* func(void* arg)
{
static int ret=10;
printf("func:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func:%d\n",*((int*)arg));
sleep(1);
pthread_mutex_lock(&mutex);
while(1){
printf("func:data=%d\n",data++);
if(data==3){//当data==3才退出
printf("func:data=%d\n",data);
pthread_mutex_unlock(&mutex);
pthread_exit((void*)&ret);
}
}
}
void* func1(void* arg)
{
static int ret=10;
printf("func1:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func1:%d\n",*((int*)arg));
while(1){
printf("func1:data=%d\n",data);
pthread_mutex_lock(&mutex);
data++;
pthread_mutex_unlock(&mutex);
//pthread_exit((void*)&ret);
sleep(1);
}
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
pthread_t thread;
pthread_t thread1;
int ret;
int ret1;
int arg=100;
int* pret;
int* pret1;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
pthread_mutex_init(&mutex,NULL);//before create pthread
ret=pthread_create(&thread,NULL,&func,(void*)&arg);
if(ret!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,(void**)&pret);
printf("main:ret %d\n",*pret);
printf("\n");
ret1=pthread_create(&thread1,NULL,&func1,(void*)&arg);
if(ret1!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
while(1);{
printf("main:data=%d\n",data);
sleep(1);
}
pthread_join(thread,(void**)&pret1);
printf("main:ret1 %d\n",*pret1);
return 0;
}
四、什么情况会造成死锁(面试会问)
死锁的情况一般发生在至少有两个锁的状态下。当A进程持有一个锁1时,同时持有锁2,但是B进程此时持有锁2,同时也想持有锁1。此时就发生互相等待对方导致进程阻塞呈现一个僵持的局面,谁也无法往下执行。
五、条件变量(一般和互斥锁配合使用)
1.条件变量初始化
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
//函数参数一配置为初始化值的地址
//参数二用默认的方式初始化,restrict attr,一般配置为NULL
2.等待一个条件变量
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
//参数一:同上。
//参数二 :即为锁,这个锁用来解开唤醒这个条件变量的所控制的线程,可以解开这个锁,
3.唤醒条件变量
int pthread_cond_signal(pthread_cond_t *cond);
4.销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond)
5.唤醒所有条件变量
int pthread_cond_broadcast(pthread_cond_t *cond)
6.示例代码:
#include<stdio.h>
#include<pthread.h>
int data=0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void* func(void* arg)
{
//static int ret=10;
//printf("func:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func:%d\n",*((int*)arg));
while(1){
// int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
pthread_cond_wait(&cond,&mutex);
printf("this is for func!\n");
printf("data=%d\n",data);
data=0;
sleep(1);
}
//pthread_exit((void*)&ret);
}
void* func1(void* arg)
{
//static int ret=10;
//printf("func1:my pthread is %ld\n",(unsigned long)pthread_self());
printf("func1:%d\n",*((int*)arg));
while(1){
pthread_mutex_lock(&mutex);
data++;
printf("func1:data = %d\n",data);
if(data==3){
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
sleep(1);
//pthread_exit((void*)&ret);
}
}
int main()
{
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
// void *(*start_routine) (void *), void *arg);
pthread_t thread;
pthread_t thread1;
int ret;
int ret1;
int arg=100;
int* pret;
int* pret1;
//int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr)
//int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
pthread_cond_init(&cond,NULL);
pthread_mutex_init(&mutex,NULL);//before create pthread
ret=pthread_create(&thread,NULL,&func,(void*)&arg);
if(ret!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
//printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
//printf("main:ret %d\n",*pret);
printf("\n");
ret1=pthread_create(&thread1,NULL,&func1,(void*)&arg);
if(ret1!=0){
printf("create pthread failed!\n");
}
printf("create pthread ok!\n");
//printf("main: my pthread is %ld\n",(unsigned long)pthread_self());
pthread_join(thread,NULL);
pthread_join(thread1,NULL);
//printf("main:ret1 %d\n",*pret1);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}