LINUX 内核的几种锁介绍
linux内核调度与spinlock的相互关系

linux内核调度与spinlock的相互关系
嵌入式linux中文站关于自旋锁用法介绍的文章,已经有很多,但有些细节的地方点的还不够透,因此我们在这里将着重介绍自旋锁相关的知识。
一、自旋锁(spinlock)简介
自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。
这点可以应用在多处理机器、或运行在单处理器上的抢占式内核中需要的锁定服务。
二、信号量简介
这里也介绍下信号量的概念,因为它的用法和自旋锁有相似的地方。
Linux中的信号量是一种睡眠锁。
如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。
这时处理器获得自由去执行其它代码。
当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
三、自旋锁和信号量对比
在很多地方自旋锁和信号量可以选择任何一个使用,但也有一些地方只能选择某一种。
下面对比一些两者的用法。
表1-1自旋锁和信号量对比
应用场合
信号量or自旋锁
低开销加锁(临界区执行时间较快)
优先选择自旋锁
低开销加锁(临界区执行时间较长)
优先选择信号量
临界区可能包含引起睡眠的代码
不能选自旋锁,可以选择信号量。
锁的实现原理

锁的实现原理
锁的实现原理是通过一种算法或者机制,来保证在多线程或多进程并发执行时,对共享资源的访问进行同步和互斥。
常见的锁机制有互斥锁(Mutex Lock)、读写锁(ReadWrite Lock)、信号量(Semaphore)、条件变量等。
其中最常用的是互斥锁。
互斥锁通过在代码块中加锁的方式,来保证同一时间只有一个线程(或进程)可以进入该代码块,从而保证对共享资源的独占访问。
具体的实现原理如下:
1. 初始化锁:创建一种数据结构来表示锁的状态,通常包括一个标志位,用于表示锁的状态(是否被占用)。
2. 加锁:当一个线程(或进程)需要访问共享资源时,首先尝试获取锁。
如果锁的状态为未占用,则将锁的状态标志位设为占用,并允许该线程(或进程)进入临界区域,即访问共享资源;如果锁的状态为已占用,则该线程(或进程)进入等待状态,直到锁的状态可用。
3. 解锁:当一个线程(或进程)结束对共享资源的访问时,释放锁,即将锁的状态标志位设为未占用,以允许其他线程(或进程)获取锁访问共享资源。
4. 等待和唤醒:当一个线程(或进程)无法获取锁时,处于等待状态,直到锁的状态可用。
此时,其他线程(或进程)可以通过某种机制(如条件变量)通知等待的线程(或进程),使其重新尝试获取锁。
锁的实现原理可以基于硬件指令、操作系统的功能或者编程语言提供的库函数等。
不同的锁机制在实现细节上可能有所不同,但核心思想是相通的,即通过对锁的状态进行管理,来保证共享资源的访问顺序和一致性,避免并发访问导致的数据竞争和未定义行为。
总之,锁的实现原理是基于同步和互斥的机制,通过对锁的加锁和解锁操作来保证多线程或多进程的安全并发访问共享资源。
Linux内核:RCU机制与使用

Linux内核:RCU机制与使⽤Linux 内核:RCU机制与使⽤背景学习Linux源码的时候,发现很多熟悉的数据结构多了__rcu后缀,因此了解了⼀下这些内容。
介绍RCU(Read-Copy Update)是数据同步的⼀种⽅式,在当前的Linux内核中发挥着重要的作⽤。
RCU主要针对的数据对象是链表,⽬的是提⾼遍历读取数据的效率,为了达到⽬的使⽤RCU机制读取数据的时候不对链表进⾏耗时的加锁操作。
这样在同⼀时间可以有多个线程同时读取该链表,并且允许⼀个线程对链表进⾏修改(修改的时候,需要加锁)。
RCU适⽤于需要频繁的读取数据,⽽相应修改数据并不多的情景,例如在⽂件系统中,经常需要查找定位⽬录,⽽对⽬录的修改相对来说并不多,这就是RCU发挥作⽤的最佳场景。
RCU(Read-Copy Update),是 Linux 中⽐较重要的⼀种同步机制。
顾名思义就是“读,拷贝更新”,再直⽩点是“随意读,但更新数据的时候,需要先复制⼀份副本,在副本上完成修改,再⼀次性地替换旧数据”。
这是 Linux 内核实现的⼀种针对“读多写少”的共享数据的同步机制。
RCU机制解决了什么在RCU的实现过程中,我们主要解决以下问题:1、在读取过程中,另外⼀个线程删除了⼀个节点。
删除线程可以把这个节点从链表中移除,但它不能直接销毁这个节点,必须等到所有的读取线程读取完成以后,才进⾏销毁操作。
RCU中把这个过程称为宽限期(Grace period)。
2、在读取过程中,另外⼀个线程插⼊了⼀个新节点,⽽读线程读到了这个节点,那么需要保证读到的这个节点是完整的。
这⾥涉及到了发布-订阅机制(Publish-Subscribe Mechanism)。
3、保证读取链表的完整性。
新增或者删除⼀个节点,不⾄于导致遍历⼀个链表从中间断开。
但是RCU并不保证⼀定能读到新增的节点或者不读到要被删除的节点。
RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。
kernel内核锁 完全解析

Kernel Locking 中文版Unreliable Guide To LockingRusty Russell<rusty@.au>翻译:albcamus <albcamus@>©Copyright 2003 Rusty RussellThis documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USAFor more details see the file COPYING in the sourcedistribution of Linux.第1章. 介绍欢迎进入Rusty优秀的《Unreliable Guide to Kernel Locking》细节。
linux xlock 用法

linux xlock 用法xlock 是 Linux 系统中一个用于锁定屏幕的命令行工具。
它可以防止未经授权的访问并保护您的计算机中的个人信息。
在本文中,我将向您介绍 xlock 的用法。
xlock 命令的基本用法非常简单。
只需在终端中输入 xlock,按下回车键即可锁定屏幕。
在屏幕被锁定的状态下,任何人都需要输入您的登录密码才能解锁屏幕并获得对计算机的访问权限。
除了基本功能外,xlock 还提供了许多定制选项。
您可以使用命令行参数来调整锁屏效果,例如更改屏幕保护程序、调整锁定时的动画效果等。
以下是一些常用的选项:1. -mode 参数允许您选择不同的屏幕保护程序模式。
例如,您可以使用 -mode matrix 来显示类似《黑客帝国》中的代码矩阵效果。
2. -timeout 参数允许您设置自动锁定的时间间隔。
默认情况下,xlock 会根据计算机的内置设置来自动锁定屏幕。
但是,通过使用 -timeout 参数,您可以自定义屏幕锁定的时间间隔。
例如,使用 -timeout 300 将在计算机空闲 5 分钟后自动锁定屏幕。
3. -password 参数允许您设置自定义的解锁密码。
默认情况下,xlock 将使用您的登录密码作为解锁密码。
但是,如果您希望设置一个不同的密码,可以使用 -password 参数。
例如,使用 -password mypassword 将设置密码为 "mypassword"。
4. -remote 参数允许远程锁定屏幕。
如果您的计算机处于网络环境中,您可以使用 -remote 参数通过网络远程锁定计算机的屏幕。
这对于防止未经授权的访问非常有用。
综上所述,xlock 是 Linux 系统中一个简单而功能强大的屏幕锁定工具。
通过使用不同的命令行参数,您可以自定义锁定屏幕的效果和行为。
无论是保护个人信息还是防止未经授权的访问,xlock 都是一个非常有用的工具。
希望本文对您有所帮助!。
Linux命令行下的文件加密和解密技巧

Linux命令行下的文件加密和解密技巧Linux操作系统提供了强大的命令行工具,使得文件的加密和解密操作变得相对简单和高效。
本文将介绍在Linux命令行下实现文件加密和解密的技巧。
以下是具体内容:一、加密文件1. 使用 OpenSSL 加密文件OpenSSL 是一个强大的开源加密工具包,可以用于加密和解密文件。
要使用 OpenSSL 加密文件,请按照以下步骤操作:(1)打开终端窗口,并导航到要加密的文件所在的目录。
(2)运行以下命令,用于将文件加密,并生成加密后的文件:openssl enc -aes-256-cbc -salt -in 文件名 -out 加密后的文件名其中,-aes-256-cbc 是指使用 AES 256 位加密算法和 CBC 模式进行加密。
您还可以选择其他的加密算法和模式,根据您的具体需求进行调整。
2. 使用 GPG 加密文件GPG(GNU Privacy Guard)是一个开源的加密软件,用于进行文件和文本的加密和解密。
要使用 GPG 加密文件,请按照以下步骤操作:(1)确保您已经安装了 GPG 工具包。
如果没有安装,可以运行以下命令进行安装:sudo apt-get install gnupg(2)打开终端窗口,并导航到要加密的文件所在的目录。
(3)运行以下命令,用于将文件加密,并生成加密后的文件:gpg -c 文件名运行该命令后,系统会提示您输入一个加密密码。
请确保密码的安全性,同时请牢记该密码,因为解密文件时需要使用该密码。
二、解密文件1. 使用 OpenSSL 解密文件要使用 OpenSSL 解密文件,请按照以下步骤操作:(1)打开终端窗口,并导航到要解密的文件所在的目录。
(2)运行以下命令,用于将加密文件解密,并生成解密后的文件: openssl enc -d -aes-256-cbc -in 加密后的文件名 -out 解密后的文件名在运行该命令时,您需要提供正确的加密算法和模式,以确保成功解密文件。
Linux_C_同步_内核原子_自旋锁_互斥锁
Linux 同步方法剖析内核原子,自旋锁和互斥锁你也许接触过并发(concurrency)、临界段(critical section)和锁定,不过怎么在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制,包括原子运算符(atomic operator)、自旋锁(spinlock)、读/写锁(reader/writer lock)和内核信号量(kernel semaphore)。
本文还探讨了每种机制最适合应用到哪些地方,以构建安全高效的内核代码。
本文讨论了 Linux 内核中可用的大量同步或锁定机制。
这些机制为 2.6.23 版内核的许多可用方法提供了应用程式接口(API)。
不过在深入学习 API 之前,首先需要明白将要解决的问题。
并发和锁定当存在并发特性时,必须使用同步方法。
当在同一时间段出现两个或更多进程并且这些进程彼此交互(例如,共享相同的资源)时,就存在并发现象。
在单处理器(uniprocessor,UP)主机上可能发生并发,在这种主机中多个线程共享同一个 CPU 并且抢占(preemption)创建竞态条件。
抢占通过临时中断一个线程以执行另一个线程的方式来实现 CPU 共享。
竞态条件发生在两个或更多线程操纵一个共享数据项时,其结果取决于执行的时间。
在多处理器(MP)计算机中也存在并发,其中每个处理器中共享相同数据的线程同时执行。
注意在 MP 情况下存在真正的并行(parallelism),因为线程是同时执行的。
而在 UP 情形中,并行是通过抢占创建的。
两种模式中实现并发都较为困难。
Linux 内核在两种模式中都支持并发。
内核本身是动态的,而且有许多创建竞态条件的方法。
Linux 内核也支持多处理(multiprocessing),称为对称多处理(SMP)。
临界段概念是为解决竞态条件问题而产生的。
一个临界段是一段不允许多路访问的受保护的代码。
这段代码能操纵共享数据或共享服务(例如硬件外围设备)。
linux中的同步机制
linux中的同步机制Linux中的同步机制在Linux操作系统中,同步机制是一种重要的机制,用于控制并发访问共享资源的顺序和互斥。
它确保多个进程或线程能够有序地访问共享资源,避免数据竞争和不一致的结果。
本文将介绍Linux中常用的同步机制,包括互斥锁、条件变量、信号量和屏障等。
一、互斥锁(Mutex)互斥锁是一种最常见的同步机制,用于保护共享资源的访问。
在互斥锁的帮助下,只有一个进程或线程能够获得锁,其他进程或线程需要等待锁的释放。
Linux提供了多种互斥锁的实现,如pthread_mutex_t和std::mutex等。
使用互斥锁需要注意避免死锁和竞态条件等问题。
二、条件变量(Condition Variable)条件变量是一种用于线程间通信的同步机制,它允许线程在满足特定条件之前等待,从而避免了忙等待的问题。
在Linux中,条件变量通常与互斥锁一起使用。
当某个线程发现条件不满足时,它可以调用条件变量的等待函数将自己阻塞,直到其他线程满足条件并发出信号,唤醒等待的线程。
三、信号量(Semaphore)信号量是一种用于控制并发访问的同步机制,它可以实现对资源的计数和管理。
Linux提供了两种类型的信号量:二进制信号量和计数信号量。
二进制信号量只有两种状态(0和1),用于互斥访问共享资源;计数信号量可以有多个状态,用于限制并发访问的数量。
通过使用信号量,可以实现进程或线程之间的同步和互斥。
四、屏障(Barrier)屏障是一种用于线程同步的机制,它在多个线程到达指定点之前将它们阻塞,直到所有线程都到达后才继续执行。
屏障可以用于并行计算中的阶段同步,确保每个阶段的计算完成后再进行下一阶段的计算。
在Linux中,可以使用pthread_barrier_t来创建和操作屏障。
五、读写锁(ReadWrite Lock)读写锁是一种特殊的锁机制,用于在读操作和写操作之间提供更好的并发性。
读写锁允许多个线程同时读取共享资源,但只允许一个线程进行写操作。
linux flock参数
linux flock参数
flock是一个Linux命令,用于在shell脚本中实现文件锁。
它的参数如下:
1. -c, --close:关闭文件描述符。
使用该选项可以在执行命令之前关闭文件描述符,以防止在执行期间文件描述符被其他进程修改。
2. -e, --exclusive:独占锁。
使用该选项可以在获取文件锁时,确保没有其他进程可以同时获取相同文件的锁。
3. -n, --nonblock:非阻塞模式。
使用该选项可以在获取文件锁时,如果无法立即获取到锁,则不会阻塞等待,而是立即返回错误。
4. -s, --shared:共享锁。
使用该选项可以在获取文件锁时,允许其他进程获取相同文件的共享锁,但是不允许其他进程获取独占锁。
5. -u, --unlock:解锁文件。
使用该选项可以释放先前获取的文件锁。
6. -w, --wait:等待模式。
使用该选项可以在获取文件锁时,如果无法立即获取到锁,则会等待直到可以获取到锁为止。
这些是flock命令的一些常用参数,可以根据实际需求选择合适的参数来实现文件锁的操作。
Linux命令行数据加密技巧使用加密和解密工具
Linux命令行数据加密技巧使用加密和解密工具在今天的数字时代,数据的安全性变得越来越重要。
无论是个人用户还是企业组织,都需要确保其敏感数据的保密性和完整性。
为了满足这一需求,Linux命令行提供了多种加密和解密工具,可以帮助我们对数据进行加密,以确保其机密性。
在本文中,我们将介绍一些常见的Linux命令行数据加密技巧,以及如何使用加密和解密工具。
1. 敏感数据的加密意义数据加密是一种将原始数据转换为密文,以防止未经授权的用户访问其内容的过程。
通过使用加密算法,我们可以将敏感数据转化为不可读的形式,只能通过解密算法来恢复原始数据。
这种加密技术可以帮助我们保护个人隐私、公司机密等重要信息。
2. Linux命令行下常用的加密算法以下是一些常见的Linux命令行下常用的加密算法:- AES(Advanced Encryption Standard):AES是一种对称加密算法,被广泛使用于保护机密数据的加密和解密过程中。
它支持不同密钥长度,包括128位、192位和256位。
- RSA(Rivest-Shamir-Adleman):RSA是一种非对称加密算法,其中使用了两个密钥,一个用于加密,另一个用于解密。
RSA算法被广泛应用于身份验证和密钥交换等领域。
- Blowfish:Blowfish是一种快速的对称加密算法,可用于加密大量数据。
它支持不同的密钥长度,包括32位到448位。
除了上述算法外,Linux命令行还支持其他加密算法,如DES (Data Encryption Standard)、3DES(Triple DES)等。
3. 使用GPG进行文件加密和解密GPG(GNU Privacy Guard)是一个开源的加密软件,可以用于加密和解密文件。
它采用了OpenPGP标准,并支持多个加密算法。
要使用GPG加密文件,可以使用以下命令:```gpg -c file.txt```上述命令将使用默认的对称加密算法对文件进行加密,并生成一个.gpg文件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
spinlock(自旋锁)、mutex(互斥量)、semaphore(信号量)、critical section(临界区)的作用与区别Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。
一般的用法是用于串行化对critical section代码的访问,保证这段代码不会被并行的运行。
Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。
对于N=1的情况,称为binary semaphore。
一般的用法是,用于限制对于某一资源的同时访问。
Binary semaphore与Mutex的差异:在有的系统中Binary semaphore与Mutex是没有差异的。
在有的系统上,主要的差异是mutex一定要由获得锁的进程来释放。
而semaphore可以由其它进程释放(这时的semaphore实际就是个原子的变量,大家可以加或减),因此semaphore 可以用于进程间同步。
Semaphore的同步功能是所有系统都支持的,而Mutex能否由其他进程释放则未定,因此建议mutex只用于保护critical section。
而semaphore则用于保护某变量,或者同步。
另一个概念是spin lock,这是一个内核态概念。
spin lock与semaphore的主要区别是spin lock是busy waiting,而semaphore是sleep。
对于可以sleep 的进程来说,busy waiting当然没有意义。
对于单CPU的系统,busy waiting 当然更没意义(没有CPU可以释放锁)。
因此,只有多CPU的内核态非进程空间,才会用到spin lock。
Linux kernel的spin lock在非SMP的情况下,只是关irq,没有别的操作,用于确保该段程序的运行不会被打断。
其实也就是类似mutex的作用,串行化对critical section的访问。
但是mutex不能保护中断的打断,也不能在中断处理程序中被调用。
而spin lock也一般没有必要用于可以sleep的进程空间。
---------------------------------------------------------------------------------------------内核同步措施为了避免并发,防止竞争。
内核提供了一组同步方法来提供对共享数据的保护。
我们的重点不是介绍这些方法的详细用法,而是强调为什么使用这些方法和它们之间的差别。
Linux使用的同步机制可以说从2.0到2.6以来不断发展完善。
从最初的原子操作,到后来的信号量,从大内核锁到今天的自旋锁。
这些同步机制的发展伴随Linux从单处理器到对称多处理器的过度;伴随着从非抢占内核到抢占内核的过度。
锁机制越来越有效,也越来越复杂。
目前来说内核中原子操作多用来做计数使用,其它情况最常用的是两种锁以及它们的变种:一个是自旋锁,另一个是信号量。
我们下面就来着重介绍一下这两种锁机制。
自旋锁自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁)。
自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。
要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。
自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。
事实上,自旋锁的初衷就是:在短期间内进行轻量级的锁定。
一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。
如果需要长时间锁定的话,最好使用信号量。
自旋锁的基本形式如下:spin_lock(&mr_lock);//临界区spin_unlock(&mr_lock);因为自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。
这点很好地满足了对称多处理机器需要的锁定服务。
在单处理器上,自旋锁仅仅当作一个设置内核抢占的开关。
如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核。
简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。
另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用。
死锁:假设有一个或多个内核任务和一个或多个资源,每个内核都在等待其中的一个资源,但所有的资源都已经被占用了。
这便会发生所有内核任务都在相互等待,但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源,无法继续运行,这便意味着死锁发生了。
自死琐是说自己占有了某个资源,然后自己又申请自己已占有的资源,显然不可能再获得该资源,因此就自缚手脚了。
信号量Linux中的信号量是一种睡眠锁。
如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。
这时处理器获得自由去执行其它代码。
当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。
信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。
信号量基本使用形式为:static DECLARE_MUTEX(mr_sem);//声明互斥信号量if(down_interruptible(&mr_sem))//可被中断的睡眠,当信号来到,睡眠的任务被唤醒//临界区up(&mr_sem);信号量和自旋锁区别虽然听起来两者之间的使用条件复杂,其实在实际使用中信号量和自旋锁并不易混淆。
注意以下原则:如果代码需要睡眠——这往往是发生在和用户空间同步时——使用信号量是唯一的选择。
由于不受睡眠的限制,使用信号量通常来说更加简单一些。
如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。
理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。
另外,信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。
这意味者信号量不会对影响调度反应时间带来负面影响。
自旋锁对信号量需求建议的加锁方法低开销加锁优先使用自旋锁短期锁定优先使用自旋锁长期加锁优先使用信号量中断上下文中加锁使用自旋锁持有锁是需要睡眠、调度使用信号量---------------------------------------------------------------------------------------------临界区(Critical Section)保证在某一时刻只有一个线程能访问数据的简便办法。
在任意时刻只允许一个线程对共享资源进行访问。
如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。
临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
在使用临界区时,一般不允许其运行时间过长,只要进入临界区的线程还没有离开,其他所有试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响。
程序的运行性能。
尤其需要注意的是不要将等待用户输入或是其他一些外界干预的操作包含到临界区。
如果进入了临界区却一直没有释放,同样也会引起其他线程的长时间等待。
虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。
互斥量(Mutex)互斥(Mutex)是一种用途非常广泛的内核对象。
能够保证多个线程对同一共享资源的互斥访问。
同临界区有些类似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。
当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。
与其他几种内核对象不同,互斥对象在操作系统中拥有特殊代码,并由操作系统来管理,操作系统甚至还允许其进行一些其他内核对象所不能进行的非常规操作。
互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。
当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。
互斥量比临界区复杂。
因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
信号量(Semaphores)信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。
它指出了同时访问共享资源的线程最大数目。
它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。
在用CreateSemaphore()创建信号量时即要同时指出允许的最大资源计数和当前可用资源计数。
一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。
但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能在允许其他线程的进入,此时的信号量信号将无法发出。
线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源计数加1。
在任何时候当前可用资源计数决不可能大于最大资源计数。
信号量是通过计数来对线程访问资源进行控制的,而实际上信号量确实也被称作Dijkstra计数器。
PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。
信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。
P操作申请资源:(1)S减1;(2)若S减1后仍大于等于零,则进程继续执行;(3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。
V操作释放资源:(1)S加1;(2)若相加结果大于零,则进程继续执行;(3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。