IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 嵌入式Linux系统编程学习之二十九线程的互斥 -> 正文阅读

[系统运维]嵌入式Linux系统编程学习之二十九线程的互斥


前言

??在 Posix Thread 中定义了一套专门用于线程互斥的 mutex 函数。mutex 是一种简单的加锁方法,用来控制对共享资源的存取,这个互斥锁只有两种状态(上锁和解锁),可以把互斥锁看作某种意义上的全局变量。为什么需要加锁,就是因为多个线程共用进程的资源,要访问的是公共区间时(全局变量),当一个线程访问时,需要加上锁以防止另外的线程对它进行访问,以实现资源的独占。在一个时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程才能够对共享资源进行操作。若其他线程希望上锁一个已经上锁了的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。
??互斥锁有三种类型:快速锁、嵌套锁(递归锁)、检错锁。
??互斥锁有两种创建(初始化)方法:静态方式(使用宏)和动态方式(用函数创建)。
??互斥锁有五个函数:创建(初始化)锁、加锁、解锁、测试加锁、销毁锁。
??互斥锁在创建(初始化)的时候必须指定类型,如果用函数创建锁,则由函数的第 2 个参数指定锁的类型。


一、创建和销毁锁

??有两种方法创建互斥锁:静态方式和动态方式。

  • 静态方式
    POSIX 定义了一个宏 PTHREAD_MUTEX_INITIALIZER 来静态初始化互斥锁,方法如下:
	pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

??在 Linux Threads 实现中,pthread_mutex_t 是一个结构,而 PTHREAD_MUTEX_INITIALIZER 则是一个宏常量。

  • 动态方式
    动态方式采用 pthread_mutex_init 函数来初始化互斥锁,API 定义如下:
	#include <pthread.h>
	int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

??其中 mutexattr 用于指定互斥锁属性,如果为 NULL 则使用默认属性,通常为 NULL 。
??pthread_mutex_destroy 函数用于注销一个互斥锁,API 定义如下:

	int pthread_mutex_destroy(pthread_mutex_t *mutex);

??销毁一个互斥锁意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在 Linux 中,互斥锁并不占用任何资源,因此 Linux Threads 中的 pthread_mutex_destroy 函数除了检查锁状态以外(锁定状态则返回 EBUSY)没有其他动作。

二、互斥锁属性

??互斥锁属性结构体的定义为:

	typedef struct
	{
		int __mutexkind;
	}pthread_mutexattr_t;

??互斥锁的属性在创建锁的时候指定,在 Linux Threads 实现中仅有一个锁类型属性 _mutexkind,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同,也就是是否阻塞等待,有 3 个值可供选择。
?(1)PTHREAD_MUTEX_TIMED_NP,这是默认值(直接写 NULL 就是表示这个默认值),也就是普通锁(或快速锁)。当一个线程加锁以后,其余请求锁的线程将形成一个阻塞等待队列,并在解锁后按优先级获得锁,这种锁策略保证了资源分配的公平性。
??示例:初始化一个快速锁

	pthread_mutex_t lock;
	pthread_mutex_init(&lock, NULL);

?(2)PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁(递归锁)。允许同一个线程对同一个锁成功获得多次,并通过多次 unlock 解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
??示例:初始化一个嵌套锁

	pthread_mutex_t lock;
	pthread_mutexattr_t mutexattr;
	mutexattr.__mutexkind=PTHREAD_MUTEX_RECURSIVE_NP;
	pthread_mutex_init(&lock, &mutexattr);

?(3)PTHREAD_MUTEX_ERRORCHECK_NP,检错锁。如果同一个线程请求同一个锁,则返回 EDEADLK ,否则与 PTHREAD_MUTEX_TIMED_NP 类型动作相同,这样就保证了当不允许多次加锁时不会出现最简单情况下的死锁。
??初始化一个检错锁

	pthread_mutex_t lock;
	pthread_mutexattr_t mutexattr;
	mutexattr.__mutexkind=PTHREAD_MUTEX_ERRORCHECK_NP;
	pthread_mutex_init(&lock, &mutexattr);

??与上面的锁类型相对应,有 3 种类型的静态锁:
??快速静态锁:pthread_mutex_t fastmutex=PTHREAD_MUTEX_INITIALIZER;
??递归锁:pthread_mutex_t recmutex=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
??检错锁:pthread_mutex_t errchkmutex=PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; 。

三、锁操作

??锁操作主要包括:

	int pthread_mutex_lock(pthread_mutex_t *mutex);		//加锁
	int pthread_mutex_unlock(pthread_mutex_t *mutex);	//解锁
	int pthread_mutex_trylock(pthread_mutex_t *mutex);	//测试加锁
  • pthread_mutex_lock:加锁,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。对于普通锁,解锁者可以是同进程内的任何线程;而检错锁和嵌套锁则必须由加锁者解锁才有效,否则返回 EPERM ;在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。
  • pthread_mutex_unlock:根据不同的锁类型,可实现不同的行为。
    对于快速锁,pthread_mutex_unlock 解除锁定;
    对于递归锁,pthread_mutex_unlock 使锁上的引用计数减 1;
    对于检错锁,如果锁是本线程锁定的,则解除锁定,否则什么也不做。
  • pthread_mutex_trylock:语义与 pthread_mutex_lock 类似,如果互斥锁未被上锁则对其上锁,但不同的是,在锁已经被占据时返回 EBUSY 而不是挂起等待。

四、加锁注意事项

??如果线程在加锁后解锁前被取消,锁将永远保持锁定状态,因此如果在关键区段内有取消点存在,则必须在退出回调函数 pthread_cleanup_push / pthread_cleanup_pop 中解锁。同时不应该在信号处理函数中使用互斥锁,否则容易造成死锁。

五、加锁步骤

??线程互斥 mutex 的加锁步骤如下:
??① 定义一个全局变量的 pthread_mutex_t lock ,或者用:

	pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;	//则 main 函数中不用 init

??② 在 main 中调用 pthread_mutex_init 函数进行初始化,初始化一个互斥锁之后,其处于被解锁的状态,可以被上锁。
??③ 在子线程函数中调用 pthread_mutex_lock 加锁。
??④ 在子线程函数中调用 pthread_mutex_unlock 解锁。
??⑤ 最后在 main 中调用 pthread_mutex_destroy 函数进行销毁。


  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-11-24 08:22:22  更:2021-11-24 08:24:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:18:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码