意义:与进程一样为了使多个程序能够并发执行。
定义:进程是资源分配的最小单位。 线程是程序执行的最小单位(又被称为轻量级进程)。
线程没办法分配空间资源,依附于进程!
线程资源问题
1.一个进程里的所有线程共享一片内存(共享:表示共享内存空间,而不是说内存中的所有数据)
(1)可共享的内容:
1.静态数据
(2)私有的内容:
1.线程ID
2.堆.栈
3.程序计数器pc(记录线程运行到什么位置)
线程接口
以下函数的实现属于第三方库函数,所以在编译时需加上-lpthread来链接库函数
头文件#<pthread.h>
pthread create ( ) 线程创建函数
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
{
thread: 线程ID,需要传递 变量的地址
attr: 设置线程属性参数. 如果选择默认属性则传递NULL
start_routine: 是一个 指针函数的指针 (要求 参数void* 返回值也是void* 的函数)
传递一个线程函数.
arg: 传递给线程函数的参数,如果不需要传参则 为NULL
返回值:
0表示成功
非0 表示错误(返回错误num)
}
pthread——join()等待线程退出函数(并且回收资源)
int pthread_join(pthread_t thread, void **retval);
{
thread: 线程ID
retval: 接收线程退出状态的参数. 不关心状态就为NULL
}
pthread——detach ()线程分离函数(使线程不受其他资源影响)
线程可以分为: 结合属性 与 分离属性 ....
默认线程是结合属性
结合属性: 线程可能会相互之间造成影响(有一定联系)
分离属性: 使线程完全独立执行,相互之间不会造成影响,并且线程可以自动回收资源了
int pthread_detach(pthread_t thread);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
pthread_t tid1, tid2;
void *MythreadFun(void *arg)
{
int n = 5;
while(n)
{
sleep(1);
printf("thread1-----------\n");
}
pthread_exit(NULL); //与return退出没有区别.
//return;
}
void *MythreadFun2(void *arg)
{
int n = 5;
while(n)
{
sleep(1);
printf("thread2------------\n");
//sleep(5);
/* if(0 != pthread_cancel(tid1))
{
perror("cancel");
break;
}*/
}
pthread_exit("thread2 quit");
}
int main(int argc, char *argv[])
{
char *quit_msg = NULL;
pthread_attr_t attr;
if(0 != pthread_attr_init(&attr))
{
perror("init");
return -1;
}
if(0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
{
perror("setdetach");
return -1;
}
if(0 != pthread_create(&tid1, &attr, MythreadFun, NULL))
{
perror("create");
return -1;
}
if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
{
perror("create2");
return -1;
}
if(0 != pthread_detach(tid2)) //设置分离属性.
{
perror("detach");
return -1;
}
/*
if(0 != pthread_join(tid1, NULL))
{
perror("join");
return -1;
}
*/
while(1)
{
sleep(1);
printf("mainThread---------\n");
}
return 0;
}
pthread_self () 获取指定线程
pthread_t pthread_self(void);
{
返回线程id
}
pthread_cancel 结束指定线程
int pthread_cancel(pthread_t thread);
{
结束指定线程. 但是不能指定分离属性的线程
}
pthread_exit 线程退出函数(相当于普通函数return)
void pthread_exit(void *retval);
{
reatval: 设置线程退出状态.
}
线程的同步和互斥
1.同步
使得线程之间按照某一种顺序来执行,这就是同步的概念
实现方式:
1.信号量
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
int flag = 0;
int m = 1;
void *MythreadFun(void *arg)
{
int n = 1;
while(n)
{
if(flag == 0)
{
printf("thread1-----------\n");
m++;
flag = 1;
}
usleep(50000);
}
pthread_exit(NULL); //与return退出没有区别.
}
void *MythreadFun2(void *arg)
{
int n = 1;
while(n)
{
if(flag == 1)
{
printf("thread2****%d\n", m);
flag = 0;
}
usleep(50000);
}
pthread_exit("thread2 quit");
}
int main(int argc, char *argv[])
{
pthread_t tid1, tid2;
char *quit_msg = NULL;
if(0 != pthread_create(&tid1, NULL, MythreadFun, NULL))
{
perror("create");
return -1;
}
if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
{
perror("create2");
return -1;
}
if(0 != pthread_join(tid1, NULL)) //阻塞函数,等待指定线程退出.
{
perror("join");
return -1;
}
pthread_join(tid2, (void**)&quit_msg);
printf("%s\n", quit_msg);
while(1)
{
sleep(1);
printf("mainThread---------\n");
}
return 0;
}
2.条件变量
2.互斥
对临界资源的一种保护措施,在线程访问该资源的时候其他线程不能访问
实现方式:
1.互斥锁
其实信号量与条件变量也能实现互斥
注意:互斥锁不能直接用于锁程序代码,只能锁临界资源
互斥锁接口:
{
初始化锁:int pthread_mutex_init(pthread_mutex_t *mutex, const
pthread_mutexattr_t *mutexattr);
{
mutex: 锁变量的地址
mutexattr: 为NULL使用默认属性
}
加锁:
解锁:
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
int m1=0;
int m2=0;
pthread_mutex_t mutex;
void *MythreadFun(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
++m1;
++m2;
pthread_mutex_unlock(&mutex);
//usleep(5000);
}
pthread_exit(NULL); //与return退出没有区别.
}
void *MythreadFun2(void *arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
if(m1 == m2)
{
printf("相等---\n");
}
else
{
printf("不相等--- #%d\n", m1-m2);
}
//usleep(5000);
pthread_mutex_unlock(&mutex);
}
pthread_exit("thread2 quit");
}
int main(int argc, char *argv[])
{
pthread_t tid1, tid2;
char *quit_msg = NULL;
pthread_mutex_init(&mutex, NULL);
if(0 != pthread_create(&tid1, NULL, MythreadFun, NULL))
{
perror("create");
return -1;
}
if(0 != pthread_create(&tid2, NULL, MythreadFun2, NULL))
{
perror("create2");
return -1;
}
if(0 != pthread_join(tid1, NULL)) //阻塞函数,等待指定线程退出.
{
perror("join");
return -1;
}
pthread_join(tid2, (void**)&quit_msg);
printf("%s\n", quit_msg);
while(1)
{
sleep(1);
printf("mainThread---------\n");
}
return 0;
}
练习题:
利用信号量实现线程同步. 例子: 创建两个线程,一个全局变量n=0,要求一个线程对n++, 另外一个线程打印n,要求输出结果必须是0,1,2,3,4,5,6...这个顺序
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
int n=0;
sem_t sem_g,sem_p;
void *myfun1(void *arg)
{
while(1)
{
sem_wait(&sem_g);
usleep(50000);
n++;
sem_post(&sem_p);
}
pthread_exit(NULL);
}
void *myfun2(void *arg)
{
while(1)
{
sem_wait(&sem_p);
usleep(50000);
printf("***%d*****\n",n);
sem_post(&sem_g);
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
sem_init(&sem_g,0,1);
sem_init(&sem_p,0,2);
pthread_t tid1,tid2;
if(0!=pthread_create(&tid1,NULL,myfun1,NULL))
{
perror("pthread_create");
return -1;
}
if(0!=pthread_create(&tid1,NULL,myfun2,NULL))
{
perror("pthread_create");
return -1;
}
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
sem_destroy(&sem_g);
sem_destroy(&sem_p);
return 0;
}
运行
结果: