学习笔记,小白可以相互学习,大佬看到能告诉咱理解不对的地方就好了。
1.线程基础
为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程。
在同一个进程中创建的线程共享该进程的地址空间。
Linux里同样用task_struct来描述一个线程。线程和进程都参与统一的调度。
通常线程指的是共享相同地址空间的多个任务。
使用多线程的好处:大大提高了任务切换的效率。避免了额外的TLB&cache的刷新。
编译时要加库文件-lpthread
可执行的指令 |
静态数据 |
进程中打开的文件描述符 |
信号处理函数 |
当前工作目录 |
用户ID |
用户组ID |
线程ID(TID) |
PC(程序计数器)和相关寄存器 |
堆栈(局部变量,返回地址) |
错误号(errno) |
信号掩码和优先级 |
执行状态和属性 |
创建线程 |
删除线程 |
控制线程 |
return | 返回函数 |
exit | 退出进程 |
pthread_exit | 线程的退出 |
函数
头文件 | #include<pthread.h> |
原型 | int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*routine)(viod *),void *arg) |
参数 | thread:创建的线程 |
attr:指定线程的属性,NULL表示缺省属性 | |
routine:线程执行的函数 | |
arg:传递给线程执行的函数的参数 | |
返回值 | 成功:0 |
出错:返回错误号 |
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
pthread_t thread;
void *thread_func(void * arg)
{
printf("arg:%s\n",(char *)arg);
while(1)
{
sleep(1);
printf("nihao\n");
}
}
int main()
{
char buf[] = "hello world";
if( 0 != pthread_create(&thread,NULL,thread_func,buf))
{
perror("pthread_create");
exit(-1);
}
while(1)
{
sleep(1);
printf("hello world \n");
}
return 0;
}
头文件 | #include<prhread.h> |
原型 | int pthread_join(pthread_t thread,void **value_ptr) |
参数 | thread:要等待的线程 value_ptr:指针*value_ptr指向的线程返回的参数 |
返回值 | 成功:0 出错:返回错误号 |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
pthread_t thread;
void *thread_func(void *arg)
{
int i;
for (i = 0; i < 5; i++) {
sleep(1);
printf("arg: %s\n", (char *)arg);
}
pthread_exit("thread exit!");
}
int main()
{
if (0 != pthread_create(&thread, NULL, thread_func, "hello world")) {
perror("pthread_create");
exit(-1);
}
printf("pthread_create success!\n");
void *ptr = NULL;
if (0 != pthread_join(thread, &ptr)) {
perror("pthread_join");
exit(-1);
}
printf("ptr: %s\n", (char *)ptr);
return 0;
}
头文件 | #include<pthread.h> |
原型 | void pthread_exit(void *value_ptr) |
参数 | value_ptr:线程退出时返回的值 |
头文件 | #include<pthread.h> |
原型 | int pthread_cancel(pthread_t thread) |
参数 | thread:要取消的线程 |
返回值 | 成功:0 出错:返回错误号 |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
pthread_t thread;
void *thread_func(void *arg)
{
int i;
for (i = 0; i < 5; i++) {
sleep(1);
printf("arg: %s\n", (char *)arg);
}
pthread_exit("thread exit!");
}
int main()
{
if (0 != pthread_create(&thread, NULL, thread_func, "hello world")) {
perror("pthread_create");
exit(-1);
}
printf("pthread_create success!\n");
sleep(2);
if (0 != pthread_cancel(thread)) {
perror("pthread_cancel");
void *ptr = NULL;
if (0 != pthread_join(thread, &ptr)) {
perror("pthread_join");
exit(-1);
}
printf("ptr: %s\n", (char *)ptr);
}else
printf("thread canceled\n");
return 0;
}
2.线程同步和互斥
2.1线程间机制
多线程共享一个进程的地址空间
优点:线程间很容易进行通信
缺点:多个线程同时访问共享对象时需要引入同步和互斥机制
2.2线程间同步
同步指的是多个任务(线程)按照约定的顺序相互配合完成一件事情。
1968年,Edsgar Dijkstra基于信号量的概念提出了一种同步机制。
由信号量来决定线程是否继续运行还是阻塞等待。
2.3P/V操作
信号量代表某一类资源,其值表示系统中该资源的数量。
信号量是一个受保护的变量,只能通过三种操作来访问
1.初始化(设定变量开始资源的数量) |
2.P操作(申请资源,同时资源数目减一) |
3.V操作(释放资源,同时资源数目加一) |
信号量的值是为非负整数
(二值信号量:值只有0和1,0表示资源不可用,1可用)
(计数信号量:表示有多少块资源)
P(S)含义如下:
if(信号量的值大于0)
{
申请资源的任务继续运行;信号量的值减一;
}
else
{
申请资源的任务阻塞;
}
V(S)含义如下:
if(没有任务等待该资源)
{
信号量的值加一;
}
else
{
唤醒第一个等待的任务,让其继续运行;
}
头文件 | #include<semaphore.h> |
原型 | int sem_init(sem_t *sem,int pshared,unsigned int value) |
参数 | sem:初始化的信号量 pshared:信号量的共享范围 (0:线程间使用,非0:进程间使用) value:信号量的初值(非负整数) |
返回值 | 成功:0 出错:-1 |
头文件 | #include<semaphore.h> |
原型 | int sem_wait(sem_t *sem) |
参数 | sem;信号量 |
返回值 | 成功:0 出错:-1 |
头文件 | #include<semaphore.h> |
原型 | int sem_post(sem_t *sem) |
参数 | sem;信号量 |
返回值 | 成功:0 出错:-1 |
2.4线程间互斥
引入互斥锁的目的是用来保证共享资源的完整性
互斥锁主要用来保护临界资源
每个临界资源都由一个互斥锁来保护,任何时刻最多只能有一个线程能访问该资源(线程不能同时执行)
函数
头文件 | #include<pthread.h> |
原型 | int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_ *attr) |
参数 | mutex:互斥锁 attr:互斥锁属性//NULL表示缺省属性 |
返回值 | 成功:0 出错:-1 |
头文件 | #include<pthread.h> |
原型 | int pthread_mutex_lock(pthread_mutex_t *mutex) |
参数 | mutex:互斥锁 |
返回值 | 成功:0 出错:返回错误号 |
头文件 | #include<pthread.h> |
原型 | int pthread_mutex_unlock(pthread_mutex_t *mutex) |
参数 | mutex:互斥锁 |
返回值 | 成功:0 出错:返回错误号 |
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
#include <semaphore.h>
pthread_t thread;
sem_t sem_w, sem_r;
char buf[100];
void *thread_func(void *arg) //读
{
while (1) {
sem_wait(&sem_r);
fputs(buf, stdout);
sem_post(&sem_w);
}
}
int main()
{
if (0 != sem_init(&sem_w, 0, 1)) {
perror("sem_init sem_w");
exit(-1);
}
if (0 != sem_init(&sem_r, 0, 0)) {
perror("sem_init sem_r");
exit(-1);
}
if (0 != pthread_create(&thread, NULL, thread_func, NULL)) {
perror("pthread_create");
exit(-1);
}
while (1) { //写
sem_wait(&sem_w);
fgets(buf, sizeof(buf), stdin);
sem_post(&sem_r);
}
return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
int count = 0;
int value1, value2;
pthread_t thread;
pthread_mutex_t mutex;
void *thread_func(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
if (value1 != value2)
printf("%d, %d\n", value1, value2);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
if (0 != pthread_mutex_init(&mutex, NULL)) {
perror("pthread_mutex_init");
exit(-1);
}
if (0 != pthread_create(&thread, NULL, thread_func, NULL)) {
perror("pthread_create");
exit(-1);
}
while (1) {
count++;
pthread_mutex_lock(&mutex); //加锁
value1 = count;
value2 = count;
pthread_mutex_unlock(&mutex); //解锁
}
}
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
//设计一个多线程程序,实现一个整型数组
//一个线程,正序打印
//另外一个线程,倒序打印
pthread_t thread;
sem_t sem_w;
sem_t sem_r;
pthread_mutex_t mutex;
int buf[10] = {};
void *thread_func(void *arg)//正序打印
{
int j;
while(1)
{
sem_wait(&sem_w);
for(j = 0; j < 10; j++)
{
scanf("%d,",&buf[9-j]);
}
for(j = 0; j < 10; j++)
{
printf("%d",buf[9-j]);
}
printf("\n");
sem_post(&sem_r);
}
}
int main()
{
if( 0 != sem_init(&sem_w,0,1))
{
perror("sem_init sem_w");
exit(-1);
}
if( 0 != sem_init(&sem_r,0,0))
{
perror("sem_init sem_r");
exit(-1);
}
if( 0 != pthread_create(&thread,NULL,thread_func,NULL))
{
perror("pthread_create");
exit(-1);
}
//倒序打印
int j;
while(1)
{
sem_wait(&sem_r);
for(j = 0; j < 10;j++)
{
printf("%d--",buf[j]);
}
printf("\n");
sem_post(&sem_w);
sleep(1);
}
printf("\n");
}
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<semaphore.h>
//设计一个多线程程序,实现一个整型数组
//一个线程,往数组里面存放数据
//另外一个线程,读取数组里面的内容
pthread_t thread;
pthread_t thread1;
sem_t sem_w;
sem_t sem_r;
int buf[10] = {0};
void *thread_func(void *arg)//写
{
sem_wait(&sem_w);
int j;
for(j = 0; j < 10; j++)
{
scanf("%d,",&buf[j]);
}
sem_post(&sem_r);
}
void *thread_func1(void *arg)//读
{
sem_wait(&sem_r);
int i;
for(i = 0; i < 10; i++)//读
{
fprintf(stdout,"%d-",buf[i]);
}
sem_post(&sem_w);
printf("\n");
}
int main()
{
if( 0 != sem_init(&sem_w,0,1))
{
perror("sem_init sem_w");
exit(-1);
}
if( 0 != sem_init(&sem_r,0,0))
{
perror("sem_init sem_r");
exit(-1);
}
if( 0 != pthread_create(&thread,NULL,thread_func,NULL))
{
perror("pthread_create");
exit(-1);
}
if( 0 != pthread_create(&thread1,NULL,thread_func1,NULL))
{
perror("pthread_create");
exit(-1);
}
void *ptr = NULL;
if( 0!= pthread_join(thread,&ptr))
{
perror("pthread_join");
exit(-1);
}
void *ptr1 = NULL;
if( 0!= pthread_join(thread1,&ptr1))
{
perror("pthread_join1");
exit(-1);
}
//pthread_join(thread,NULL);//等待线程结束
//pthread_join(thread1,NULL);
}
#include<stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex;
pthread_t thread;
void *buf = NULL;
void reserve(int *buf,int len)
{
int i = 0;
int j = 0;
j = len -1;
int k = 0;
pthread_mutex_lock(&mutex);
for(i = 0;i < len/2;i ++)
{
buf[i] ^= buf[j];
buf[j] ^= buf[i];
buf[i] ^= buf[j];
j--;
}
for(k = 0; k < 10; k++)
{
printf("%2d",buf[k]);
fflush(stdout);
}
printf("\n");
pthread_mutex_unlock(&mutex);
}
void * thread_fun(void *arg)
{
int *p = arg;
reserve(p,10);
pthread_exit("success");
}
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,0};
int j = 0;
if(0 != pthread_mutex_init(&mutex,NULL))
{
printf("pthread_mutex_init is falil\n");
exit(-1);
}
else
{
//创建线程
if(0 != pthread_create(&thread,NULL,thread_fun,a))
{
perror("pthread_create");
exit(-1);
}
else
{
pthread_mutex_lock(&mutex);
for(j = 0; j < 10; j ++)
{
printf("%d\n",a[j]);
}
pthread_mutex_unlock(&mutex);
pthread_join(thread,&buf);
printf("%s\n",(char *)buf);
}
}
return 0;
}