Linux(线程的同步与互斥)学习笔记

  1. 线程的同步与互斥

1.1 基本概念

【1】临界资源:进程或线程之间共享的资源,但同一时间只能被一段指令序列所占用的资源就是所谓的临界资源。
典型的临界资源比如物理上的打印机,或是存在硬盘或内存中被多个进程/线程所共享的一些
变量和数据等。这类资源如果不被看成临界资源加以保护,那么很有可能因为访问冲突造成数据
错乱的问题。
【2】临界区:程序内访问临界资源的代码序列被称为临界区。
【3】互斥:是指同时只允许一个访问者对临界资源进行访问,具有唯一性和排它性。但互斥无法限制
访问者对资源的访问顺序,即访问是无序的。
【4】同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在
大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。

1.2 互斥锁(实现互斥)

1.2.1 简介
我们对线程的互斥主要介绍NPTL库自带的
pthread_mutex_t互斥锁只有两种状态:上锁和解锁
上锁(拥有互斥锁): 一个线程在访问临界资源前必须先获得获得互斥锁(上锁),如果一个线程对一个已经上锁互锁锁再试图上锁,就会陷入阻塞直到某个线程
释放为止
解锁(释放互斥锁): 线程访问完临界资源之后必须释放互斥锁

1.2.2 操作函数
【1】初始化 (互斥锁必须初始化后才可以使用)
a.动态初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
函数参数:
[1] mutex : 互斥锁
[2] attr : 互斥锁的属性(NULL 使用默认属性)
返回值:
成功 返回 0
失败 返回 errnum
b.静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

【2】销毁互斥锁(对于互斥锁的所有操作完成之后)
int pthread_mutex_destroy(pthread_mutex_t *mutex);
函数参数:
mutex : 互斥锁
返回值:
成功 返回 0
失败 返回 errnum

【3】上锁
#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);
函数参数:
mutex : 互斥锁
返回值:
成功 返回 0
失败 返回 errnum

【4】解锁
#include <pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex);
函数参数:
mutex : 互斥锁
返回值:
成功 返回 0
失败 返回 errnum

1.3 信号量/信号灯 (semaphore)(可以实现同步与互斥)

1.3.1 信号量的概念:
信号量是用来解决进程/线程之间的同步与互斥问题的一种通信机制,它表示代表某一类资源,
其值表示系统中该资源的数量(可用的)。
信号量的数据类型: sem_t
1.3.2 信号量的操作
b. P操作(申请资源)
if (信号量的值 > 0) {
申请资源的任务继续;信号量值–;
} else {
申请资源的任务阻塞
}
c. V操作(释放资源)
if (没有任务在等待该资源){
信号量的值加一;
}else{
唤醒第一个等待的任务,让其继续运行;
}

注意:一个任务申请资源时有可能被阻塞,一个任务释放资源时一定不会被阻塞

1.3.3 原子操作 (atomic operation)
所谓原子操作是指不会被线程调度机制打断的操作;
这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。

互斥锁 上锁和解锁的操作是原子的
P&V操作也是原子操作

1.3.4 信号量的类型
POSIX 信号量
(1)无名信号量 *(线程间的同步、互斥)/进程间同步互斥(共享内存)
(2)有名信号量 用于进程间同步互斥、线程
System V 信号量
主要用于进程之间的同步与互斥

1.3.5 POSIX 无名信号量API
【1】信号量的初始化
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
函数参数:
[1] sem : 信号量
[2] pshared : 表示信号量的用户
0 代表在线程中使用
!0 代表在进程中使用
[3] value : 信号量的初始值
返回值:
成功 返回 0
失败 返回 -1

【2】销毁信号量
#include <semaphore.h>

int sem_destroy(sem_t *sem);
函数参数:
[1] sem : 信号量
返回值:
成功 返回 0
失败 返回 -1

【3】p操作
#include <semaphore.h>

int sem_wait(sem_t *sem);
函数参数:
[1] sem : 信号量
返回值:
成功 返回 0
失败 返回 -1

【4】v操作
#include <semaphore.h>

int sem_post(sem_t *sem);
函数参数:
[1] sem : 信号量
返回值:
成功 返回 0
失败 返回 -1

1.3.6 信号量实现同步\互斥
【1】实现互斥
开始
|
初始化信号量值为1
| |
p操作 p操作
| |
线程1执行 线程2执行
| |
V操作 v操作
|
结束

【2】实现同步
开始
|
初始化信号量
sem1为 1,sem2为0
| |
p操作sem1 p操作sem2
| |
线程1执行 线程2执行
| |
V操作sem2 v操作sem1
|
结束

开始
|
初始化信号量
sem1为 1,sem2为0,sem3 为0
| | |
p操作sem1 p操作sem2 p操作sem3
| | |
线程1执行 线程2执行 线程3
| | |
V操作sem2 v操作sem3 v操作sem1
|
结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值