本篇文章主要介绍了"SQLite 再谈SQLite的锁",主要涉及到sqlite方面的内容,对于Android开发感兴趣的同学可以参考一下:
写在前面:SQLite封锁机制的实现需要底层文件系统的支持,不管是Linux,还是Windows,都提供了文件锁的机制,而这为SQLite提供了强大的支持。本节...
写在前面:SQLite封锁机制的实现需要底层文件系统的支持,不管是Linux,还是Windows,都提供了文件锁的机制,而这为SQLite提供了强大的支持。本节就来谈谈SQLite使用到的文件锁——主要基于Linux和Windows平台。
Linux 支持的文件锁技术主要包括建议锁(advisory lock)和强制锁(mandatory lock)这两种。此外,Linux 中还引入了两种强制锁的变种形式:共享模式强制锁(share-mode mandatory
lock)和租借锁(lease)。在这里,主要讨论建议锁(advisory lock)。
建议锁并不由内核强制实行,也就是说如果有进程不遵守“游戏规则”,不检查目标文件是否已经由别的进程加了锁就往其中写入数据,那么内核是不会加以阻拦的。因此,建议锁并不能阻止进程对文件的访问,而只能依靠各个进程在访问文件之前检查该文件是否已经被其他进程加锁来实现并发控制。进程需要事先对锁的状态做一个约定,并根据锁的当前状态和相互关系来确定其他进程是否能对文件执行指定的操作。而强制锁是由内核强制采用的文件锁——由于内核对每个read()和write()操作都会检查相应的锁,所以会降低系统性能。
对于建议锁,Linux提供两种实现方式:锁文件(lock files)和记录锁( record locking)。
(1)锁文件(lock files)
锁文件是最简单的对文件加锁的方法,每个需要加锁的数据文件都有一个锁文件(lock file)。当锁文件存在时,就认为该数据文件已经被加锁,别的进程不应该访问(但是你非要访问,Linux也不会阻止)。当锁不存在,进程就可以创建一个锁文件,然后访问相应的数据文件。只要创建锁的过程是原子的,就能保证某一时刻只有一个进程拥有该锁,这种方法保证某一时刻只有一个进程访问文件。
这种想法很简单,当一个进程想访问文件时,可以按如下方式对文件加锁:

fd = open("somefile.lck", O_RDONLY, 0644);
if (fd >= 0) {
close(fd);
printf("the file is already locked");
return 1;
} else {
/* the lock file does not exist, we can lock it and access it */
fd = open("somefile.lck", O_CREAT | O_WRONLY, 0644"); if (fd < 0) {
perror("error creating lock file");
return 1;
}
/* we could write our pid to the file */
close(fd);
}
当一个进程处理完文件后,就可以调用unlink("somefile.lck")释放锁了——本质上是删除somefile.lck文件。
上面这段代码实际上存在竞争情况,原因在于if语句块不是原子性的,进入if语句块,内核可能调度别的进程运行。更好的方式如下:
