(1) 创建互斥锁--互斥锁的初始化----pthread_mutex_init()
(2) 申请锁(上锁)---pthread_muutex_lock()
(3)释放锁(打开)--pthread_mutex_unlock()
前言
进程是系统中程序执行和资源分配的基本单位。每个进程都有自己的数据段、代码段和堆栈段,这就造成了程序在进行切换时操作系统的开销比较大。为了提高效率,操作系统有引入了另一个概念——线程,也称为轻量级进程。
一、线程
进程特点:
1、每一个进程之间的地址空间是相互独立的;
2、每一个进程都有一个task_struct任务结构体;
3、在进行进程切换时,需要不断刷新cache缓存,比较消耗资源;
4、为了减少cache舒心是的资源消耗,引入轻量级进程------线程。
线程特点:
1、同一个进程创建的多个线程,共用同一个进程的地址空间;
2、进程创建线程后,我们把原本进程也可以称为线程,称为主线程。
进程被称为是最小的资源分配单位;
线程被称为CPU最小的任务调度单位。
线程公共数据:用户名、用户组名、静态数据、全局数据、文件描述符;
线程私有数据:线程ID、pc、优先级、状态、属性、堆栈。
二、线程相关接口函数
1.pthread_create----创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数:
thread:表示线程对象,一个线程对应一个线程对象;
attr:线程属性,填NULL表示使用默认属性(结合属性);
start_routine:表示线程处理函数(回调函数)自己创建void *(*start_routine) (void *)---函数指针;
arg:给线程处理函数start_routine传参数(void *表示最大可以有一个),如果线程处理函数没有参数,则填NULL。
返回值:
成功返回0,失败返回错误编号。
在编译跟线程操作相关的程序时,需要链接线程 线程库的库名---pthread
代码如下(示例):
#include <stdio.h>
#include <pthread.h>
int main()
{
ptread_t pthread1;
int ret = pthread_create(&pthread1,NULL,func,NULL);//创建线程
if(ret < 0)
{
perror("pthread_create");//创建失败
exit(-1);
}
2.pthread_exit------结束线程
#include <pthread.h>
void pthread_exit(void *retval);
参数:
retval:表示线程结束信息,由pthead_join等待接收,不想返回信息填NULL 。
返回值---return value
3.pthread_join------等待线程
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
等待线程一般在主线程中调用
三、线程间的通信
线程间的通信只需要利用全局变量就可以实现。
在一个线程使用全局变量时,有可能其他线程也在访问该数据,那么某一线程视同的数据就可能遭到破坏
通过线程的同步和互斥,能够达到数据保护的效果
(1)同步:多个线程之间按照事先约定好的顺序,有先后的完成某个事件
信号量:是系统中的一种资源,本质是一个非负整数,信号量的值等于资源的个
操作信号量只能由特定函数接口才能访问 :
1.信息量的初始化----sem_init()
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
sem:信行量对象
pshared:填0表示用于线程间同步
value:信号量的初始值
返回值:
成功返回0,失败返回-1;
2.P操作(申请资源)------sem_wait()
如果有可用资源(信号量值大于0),则占用一个资源(信号量值减一,进入临界区代码);如果没有可用资源(信号量值等于0),则被阻塞,直到系统将资源分配给该任务(进入等待队列,一直等到有资源则被唤醒)。
#include <semaphore.h>
int sem_wait(sem_t *sem);
参数:
sem:信号量对象
执行过程:
if(是否有资源)
{
执行后序代码;
信号量减一;
}
else
{
阻塞等待,知道有资源唤醒为止;
}
3.V操作(释放资源)-----sem_post()
如果在该信号量的等待队列中有任务在等待资源,则唤醒一个阻塞任务。如果没有任务等待它,则释放一个资源(信号量加一)。
#include <semaphore.h>
int sem_post(sem_t *sem);
参数:
sem:信号量对象
信号量+1
if(有等待资源的程序)
{
将其唤醒;
}
P、V操作测试代码如下:
包含线程的创建,结束线程和等待线程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
void *get_data();
void *print_data();
char buf[64] = {0};
sem_t sem1;
sem_t sem2;
int main(int argc, char *argv[])
{
pthread_t thread1,thread2;
sem_init(&sem1, 0, 0);
sem_init(&sem2, 0, 1);//信号量初始化
int ret = pthread_create(&thread1,NULL,get_data,NULL);//创建线程
if(ret < 0)
{
perror("pthread_create");//创建失败,错误退出
exit(-1);
}
ret = pthread_create(&thread2,NULL,print_data,NULL);
if(ret < 0)
{
perror("pthread_create");
exit(-1);
}
pthread_join(thread1, NULL);
pthread_join(thread1, NULL);//等待线程
return 0;
}
void *get_data()
{
while(1)
{
sem_wait(&sem2);//申请资源
fgets(buf, 64, stdin);//从键盘输入数据
sem_post(&sem1);//释放资源
}
}
void *print_data()
{
while(1)
{
sem_wait(&sem1);
printf("%s", buf);
sem_post(&sem2);
}
}
(2)互斥:当一个线程使用公共数据时,其他线程都不能访问该数据(互斥锁)
临界资源:多个线程能够共同访问的数据
临界区:涉及到临界资源的代码模块
互斥是使用互斥锁保护临界资源
4.互斥锁的相关操作接口函数:
(1) 创建互斥锁--互斥锁的初始化----pthread_mutex_init()
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t *attr);
参数:
mutex:互斥锁对象(全局的)
attr:互斥锁属性,填NULL使用缺省属性
返回值:
成功返回0,失败返回-1
(2) 申请锁(上锁)---pthread_muutex_lock()
#include <pthread.h>
int pthread_muutex_lock( pthread_mutex_t *mutex);
参数:
mutex:互斥锁对象
(3)释放锁(打开)--pthread_mutex_unlock()
#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数:
mutex:互斥锁对象
互斥锁测试,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *func();
int num1 = 0;
int num2 = 0;
int count = 0;
pthread_mutex_t mutex;
int main(int argc, char *argv[])
{
pthread_t thread;
int ret = pthread_mutex_init(&mutex, NULL);
if(ret != 0)
{
perror("init failed!\n");
exit(-1);
}
ret = pthread_create(&thread, NULL, func, NULL);
if(ret < 0)
{
perror("pthread_create");
exit(-1);
}
while(1)
{
pthread_mutex_lock(&mutex);
num1 = count;
num2 = count;
count++;
pthread_mutex_unlock(&mutex);
}
return 0;
}
void *func()
{
while(1)
{
pthread_mutex_lock(&mutex);
if(num1 != num2)
{
printf("num1 = %d , num2 = %d\n",num1, num2);
}
pthread_mutex_unlock(&mutex);
}
}
总结
以上就是今天的内容,主要讲的是线程相关的接口函数以及线程间的通信,欢迎大家留评讨论!