竞争锁现在我们已经了解了如何测试文件上已经存在的锁,下面我们来看一下当两个程序在文件的同一块区域竞争锁时会出现什么情况。我们将会使用我们的lock3程序在文件的第一个位置进行加锁操作,然而一个新的程序在同样的位置尝试加锁。要完成这个例子,我们需要添加一些解锁操作。
试验--竞争锁下面是程序lock5.c,试图在文件中已被加锁的区域进行加锁操作,而不是测试文件不同部分的锁状态。
1 在#include以及声明之后,打开一个文件描述符:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
const char *test_file = “/tmp/test_lock”;
int main()
{
int file_desc;
struct flock region_to_lock;
int res;
file_desc = open(test_file, O_RDWR | O_CREAT, 0666);
if (!file_desc) {
fprintf(stderr, “Unable to open %s for read/write\n”, test_file);
exit(EXIT_FAILURE);
}
2 程序的其余部分指定文件的不同区域,并且在其上尝试不同的锁操作:
region_to_lock.l_type = F_RDLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 10;
region_to_lock.l_len = 5;
printf(“Process %d, trying F_RDLCK, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start, (int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to lock region\n”, getpid());
} else {
printf(“Process %d - obtained lock region\n”, getpid());
}
region_to_lock.l_type = F_UNLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 10;
region_to_lock.l_len = 5;
printf(“Process %d, trying F_UNLCK, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start,
(int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to unlock region\n”, getpid());
} else {
printf(“Process %d - unlocked region\n”, getpid());
}
region_to_lock.l_type = F_UNLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 0;
region_to_lock.l_len = 50;
printf(“Process %d, trying F_UNLCK, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start,
(int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to unlock region\n”, getpid());
} else {
printf(“Process %d - unlocked region\n”, getpid());
}
region_to_lock.l_type = F_WRLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 16;
region_to_lock.l_len = 5;
printf(“Process %d, trying F_WRLCK, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start,
(int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to lock region\n”, getpid());
} else {
printf(“Process %d - obtained lock on region\n”, getpid());
}
region_to_lock.l_type = F_RDLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 40;
region_to_lock.l_len = 10;
printf(“Process %d, trying F_RDLCK, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start,
(int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLK, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to lock region\n”, getpid());
} else {
printf(“Process %d - obtained lock on region\n”, getpid());
}
region_to_lock.l_type = F_WRLCK;
region_to_lock.l_whence = SEEK_SET;
region_to_lock.l_start = 16;
region_to_lock.l_len = 5;
printf(“Process %d, trying F_WRLCK with wait, region %d to %d\n”, getpid(),
(int)region_to_lock.l_start,
(int)(region_to_lock.l_start +
region_to_lock.l_len));
res = fcntl(file_desc, F_SETLKW, ®ion_to_lock);
if (res == -1) {
printf(“Process %d - failed to lock region\n”, getpid());
} else {
printf(“Process %d - obtained lock on region\n”, getpid());
}
printf(“Process %d ending\n”, getpid());
close(file_desc);
exit(EXIT_SUCCESS);
}
如果我们首先在后端运行lock3程序,然后立即运行这个新程序:
$ ./lock3 &
$ process 1845 locking file
$ ./lock
我们得到的程序输出结果如下所示:
Process 227 locking file
Process 228, trying F_RDLCK, region 10 to 15
Process 228 - obtained lock on region
Process 228, trying F_UNLCK, region 10 to 15
Process 228 - unlocked region
Process 228, trying F_UNLCK, region 0 to 50
Process 228 - unlocked region
Process 228, trying F_WRLCK, region 16 to 21
Process 228 - failed to lock on region
Process 228, trying F_RDLCK, region 40 to 50
Process 228 - failed to lock on region
Process 228, trying F_WRLCK with wait, region 16 to 21
Process 227 closing file
Process 228 - obtained lock on region
Process 228 ending
工作原理首先,程序试图使用一个共享锁锁住文件中由10到15字节的区域。这个区域已经存在一个共享锁,但是允许后续的共享锁,并且加锁操作成功。
然后程序在此区域解除共享锁,这个操作也是成功的。程序然后试图对文件的前50个字节进行解锁操作,尽管此处并没有任何锁设置。这个操作也是成功的,因为尽管这个程序在第一个位置并没有锁,解锁请求的结果就是程序在前50个字节上并没有加任何锁。
接下来,程序试图使用一个排他锁在16到21字节的区域上加锁。这个区域已经具有了一个共享锁,所以这次的新锁操作失败,因为不能创建排他锁。
此后,程序在40到50字节的区域上试图加共享锁。此区域已经存在排他锁,所以加锁操作失败。
最后,程序试图在16到21字节的区域上获得排他锁,但是这次他使用F_SETLKW命令进行等待直到获得锁。在程序的输出结果中就会出现长时的暂停,直到已经锁住此区域的lock3程序关闭文件并释放所获得的所有锁。lock5程序恢复执行,在其退出之前,成功锁住此区域。
其他的锁命令对文件加锁还有第二个方法:lockf函数。这个函数也使用文件描述符进行操作。其函数原型如下:
#include <unistd.h>
int lockf(int fildes, int function, off_t size_to_lock);
function参数的值如下:
F_ULOCK:解锁
F_LOCK:排他锁
F_TLOCK:测试并加排他锁
F_TEST:测试其他进程的锁
size_to_lock参数是要在其上进行操作的字节数,由文件中的当前偏移算起。
lockf比起fcntl接口具有更为简单的接口,主要是因为他具有更少的功能与灵活性。要使用这个函数,我们必须设置我们希望加锁的区域的起始处,然后使用要加锁的字节数进行调用。
与文件加锁的fcntl方法相类似,所有的锁都只是建议锁;他们并不会真正的阻止对于文件的读写操作。检测锁是程序的职责。在Linux中并没有定义混合使用fcntl锁与lockf锁的效果,所以我们必须决定我们希望使用哪种类型的锁,并且坚持只使用一种锁。
死锁如果不指现死锁的危险,那么对于锁的讨论就是不完整的。假设两个程序希望更新同一个文件。他们都需要同时更新1到2的字节区域。程序A选择先更新字节2,然后更新字节1。程序B试图首先更新字节1,然后更新字节2。
两个程序同时走去。程序A锁住字节2,而程序B锁住字节1。程序A试图在字节1加锁。因为这已经被程序B锁住,程序A进行等待。程序B试图锁住字节2。因为这已经被程序A锁住了,程序B也等待。
当任何一个程序都不能进行处理的形势就称之为死锁。这在数据库程序中是一个很常见的问题,因为此时大量的用户会同时访问相同的数据。大多数的商业关系型数据会检测死锁并且会自动打破死锁;而Linux内核不会。为了处理死锁这样的情况需要一些外部的介入,例如终止其中一个程序。
程序员必须清楚这种情况。当我们有多个程序在等待锁时,我们必须十分小心以避免死锁。在我们这个例子中很容易避免死锁:两个程序以相同的顺序锁住他们所需要的字节,或者是锁住更大的区域。
分享到:
相关推荐
用友主数据管理解决方案的架构分为五层: * 应用层:提供了统一的主数据管理界面 * 数据层:提供了统一的主数据存储和管理 * 服务层:提供了统一的主数据服务 * 业务流程层:提供了统一的业务流程管理 * 集成层:...
数据管理能力成熟度评估模型 数据管理能力成熟度评估模型是评价一个组织对数据管理的能力和...通过对这五个维度的评估,可以对一个组织的数据管理能力和成熟度进行评价,并为提高数据管理能力提供有价值的建议和指导。
本资源摘要信息将从华为制造业数据治理、数据管理与数据中台架构解决方案PPT.pptx中提取相关知识点,总结了数据治理、数据管理、数据中台架构等方面的重要概念和技术。 一、数据治理 * 数据治理是指对组织内所有...
五、数据安全准则 数据分类分级管理制度需要制定相应的数据安全准则,以确保数据的安全和机密性。这些准则包括: * 数据加密:对重要敏感数据进行加密,以免泄露。 * 访问控制:对数据的访问进行控制,以免非法...
DCMM模型共分为五个级别,分别是初始级、受管理级、稳健级、量化管理级和优化级,每个级别代表了不同的数据管理成熟度水平: 1. **初始级**:数据管理活动零散,缺乏统一规划和规范,主要依赖个人经验和临时性措施...
数据管理委员会是数据标准相关工作的最高决策管理组织,具体职责包括对重大数据标准相关事项进行决策,监督数据标准相关工作的开展,定期听取数据标准工作汇报,指导和推进公司数据标准化的执行。 数据分析中心负责...
### DAMA2数据管理知识体系解析 #### 一、数据管理的重要性及背景 在当今数字化时代,数据已经成为企业和组织的核心资产。随着技术的发展,我们能够测量各种事件和活动,从宇宙大爆炸的影响到人类的心跳,甚至能够...
数据资产管理平台涵盖了采集、加工、使用、评估、优化、下线等数据资产的全生命周期管理,并基于全面数据治理能力,进一步提供专业化的数据资产“管家”服务,包括资产规划、运营管理、开放管理,以及面向企业客户和...
大数据中心信息数据管理制度是规范大数据处理过程中的关键环节,旨在确保数据的安全、合规与高效使用。以下是该制度涉及的主要知识点: 1. 数据管理原则:大数据中心遵循分级管理、安全可控和充分利用的原则。这...
二、数据资产管理活动职能 (一) 数据模型管理 (二) 数据标准管理 (三) 数据质量管理 (四) 主数据管理 (五) 数据安全管理 (六) 元数据管理 (七) 数据开发管理 (八) 数据资产流通 (九) 数据价值评估 (十) 数据资产运营...
### 数据管理知识体系(第二版)—— DAMA-DMBOK #### 一、引言与背景 在当今数字化时代,数据已经成为企业运营的核心资产之一。随着云计算、大数据、人工智能等新兴技术的发展,数据管理的重要性日益凸显。企业...
五、数据管理领导小组 * 组长、副组长和小组成员的职责 * 负责组织各领域业务专家、总行各部门及分支机构开展数据管理相关工作 * 协调并推进数据管理相关工作并监督落实 * 发布数据管理相关文件并向上汇报 六、...
主数据管理包括五个方面:质量策略、标准化、来源采集、分发和维护。 1. 质量策略:确保主数据的质量和一致性,避免数据重复和冲突。 2. 标准化:确保主数据的格式和结构标准化,以便于数据的交换和共享。 3. 来源...
#### 五、GIS数据管理的独特需求 尽管传统的DBMS技术在管理表格数据和提供分布式访问方面表现出色,但对于GIS工作流程中的一些特定需求,如数据整合、编辑、确保空间数据完整性、支持长事务以及分布式数据库中的版本...
校友数据分为在校生数据管理、校友数据管理、教职工数据管理、校外导师数据管理、重要校友数据管理五个分类管理。根据学校的管理需要,可以再增加工会会员、党员、团员等多个分类进行管理。 2) 校友信息维护及在线...
3. 组织职能升级变迁:设立专门的数据管理团队,负责数据的全生命周期管理。 4. 管理手段自动智能:利用自动化工具和AI技术,提升数据处理效率和准确性。 5. 应用范围不断扩大:数据资产管理不仅限于内部业务,还...
在第五章《数据资源管理技术》中,我们深入探讨了数据管理技术的发展历程以及关键概念。 【数据管理技术的发展历史】分为两个主要阶段: 1. **人工管理阶段**:早期计算机主要用于科学计算,缺乏磁盘等直接存取的...
资产治理旨在降低数据管理的成本并提高效率。具体措施包括: 1. 数据存储治理,形成闭环,确保数据的稳定性和可访问性。 2. 数据计算治理工具,通过工具赋能资产治理,提升治理效率。 3. 治理领域和方法策略,制定...
第五部分是术语与案例,它通过介绍业界主数据管理的先行者们的实践案例,为读者提供了更直观的参考。这部分内容通过案例分析,帮助读者更好地理解主数据管理在实际业务中的应用和效果。 整体来看,白皮书是一份非常...
1. **2007-2016年**:在这一阶段,华为设立了专门的数据管理组织,发布了数据管理政策,并建立了数据管理框架。通过这些措施,华为实现了数据质量的持续提升,减少了纠错成本,提高了业务运作效率。 2. **2017年...