线程基础/线程同步和互斥

时间:2022-01-17 09:36:25

学习笔记,小白可以相互学习,大佬看到能告诉咱理解不对的地方就好了。


1.线程基础

   为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程。

在同一个进程中创建的线程共享该进程的地址空间。

Linux里同样用task_struct来描述一个线程。线程和进程都参与统一的调度。

通常线程指的是共享相同地址空间的多个任务。

使用多线程的好处:大大提高了任务切换的效率。避免了额外的TLB&cache的刷新。

编译时要加库文件-lpthread


一个进程中的多个线程共享以下资源
可执行的指令
静态数据
进程中打开的文件描述符
信号处理函数
当前工作目录
用户ID
用户组ID

每个线程私有的资源如下
线程ID(TID)
PC(程序计数器)和相关寄存器
堆栈(局部变量,返回地址)
错误号(errno)
信号掩码和优先级
执行状态和属性

NPTL线程库中提供了如下基本操作
创建线程
删除线程
控制线程

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

P操作(申请资源)
头文件 #include<semaphore.h>
原型 int  sem_wait(sem_t *sem)
参数 sem;信号量
返回值 成功:0
出错:-1


V操作(释放资源)
头文件 #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;
}