精华内容
下载资源
问答
  • 文件锁
    千次阅读
    2022-03-28 23:04:15

    文件锁的原理

    理解了文件锁的原理后,就可以理解为什么文件锁可以实现互斥与共享了。

    若A进程与B进程同时打开同一个文件,他们使用同一个文件表,使用同一个V节点,V节点指向hello这个文件,里面有一个锁链表,里面记录了锁的信息。

    加锁时,进程会检查共享的文件锁链表

    1. 如果链表上只有读锁节点
      • 所有目前其他进程对该文件只加了读锁,由于读锁时共享的,所以不管链表上有几个读节点,当前进程都能成功加读锁。
      • 图:
      • 提供:链表上可不可以存在n多个读锁节点?
      • 答:可以,因为读锁是共享的,不管别的进程有没有解读锁,所有进程都可以加读锁,每加一个读锁,链表上就多一个读锁节点,只有当解锁时节点才被删除。
    2. 如果链表上有一个写锁节点
      • 表明,当前有进程对文件加了锁,锁节点还存在,表示人家目前还没有解锁,写锁是互斥的,所以当前不能加读锁,别人解锁后才能加读锁,加锁后链表上就插入了一个读锁节点。
      • 没有解锁就表示数据没有写完,必须等到解锁后才能加读锁
      • 提问:链表上可不可能同时存在多个写锁节点?
      • 答:不可能,因为写锁是互斥的,目前只有一个进程再给文件加写锁,再解锁之前,别的进程不能加写锁。
      • 疑问:链表上会不会同时存在读锁节点和写锁节点?
      • 读锁节点和写锁节点也是互斥的,链表上有读锁节点就不可能存在写锁节点,反过来有写锁节点就不能有读锁节点。

    如果你想加锁?

    1. 如果链表上有读锁节点,别人没有解锁,读锁与写锁互斥,不能加写锁。
    2. 如果链表上有写锁节点,被人没有解锁,写锁与写锁互斥,多以当前进程不能加写锁。

    对比进程信号量?

    1. 进程信号量:进程间共享信号量集合,通过检查集合中信号量的值,从而知道自己能不能操作
    2. 文件锁:进程共享文件锁链表,通过检查链表上的锁节点,从而知道自己能不能操作。

    文件锁其他值得注意的地方

    • 在同一进程中,如果多个文件描述符指向同一文件,只要关闭其中任何一个文件描述符,那么该进程加在文件上的文件锁将会被删除,也就是该进程在"文件锁链表"上的“读锁写锁”节点会被删除。
    • 进程终止时会关闭所有打开的文件描述符,所以进程结束时会自动删除所有加的文件锁。
    • 父进程所加的文件锁,子进程不会继承,我们在讲进程控制时就说过加锁是进程各自私人事情,不能继承,就好比你爸有癌症,你也会有吗?

    一个值得理解的问题:多线程之间能不能使用文件锁?

    可以,但是线程不能使用同一个open返回的文件描述符,线程必须使用自己open所得到的文件描述符才有效。

    代码演示:

    线程使用要自己打开文件描述符

    void *pth_fun(void *pth_arg)
    {
    	int fd;
    
    	fd = open("./hello", O_RDWR|O_CREAT|O_TRUNC, 0664);
    	if (fd == -1)  print_err("./hello", __LINE__, errno); 
    	while(1)
    	{
    		SET_WRFLCKW(fd, SEEK_SET, 0, 0);
    		write(fd, "hello ", 6);
    		write(fd, "world\n", 6);
    		SET_UNFLCK(fd, SEEK_SET, 0, 0);
    	}
    	return NULL;
    }
    
    int main(int argc, char *argv[])
    {
    	int fd = -1;
    	int ret = -1;
    	pthread_t tid;
    
    	fd = open("./hello", O_RDWR|O_CREAT|O_TRUNC, 0664);
    	if (fd == -1)  print_err("./hello", __LINE__, errno); 
    
    	ret = pthread_create(&tid, NULL, pth_fun, NULL);
    	if (ret == -1) print_err("pthread_create fail", __LINE__, ret);
    
    	while(1)
    	{
    		SET_WRFLCKW(fd, SEEK_SET, 0, 0);
    		write(fd, "hello ", 6);
    		write(fd, "world\n", 6);
    		SET_UNFLCK(fd, SEEK_SET, 0, 0);
    	}
      
    	return 0;
    }
    
    更多相关内容
  • 本文实例讲述了Python使用文件锁实现进程间同步功能。分享给大家供大家参考,具体如下: 简介 在实际应用中,会出现这种应用场景:希望shell下执行的脚本对某些竞争资源提供保护,避免出现冲突。本文将通过fcntl模块...
  • 详解Linux文件锁flock

    2020-09-15 12:52:06
    主要介绍了详解Linux文件锁flock,在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock。
  • 文件锁,锁文件

    2017-12-01 20:31:42
    锁文件,可设置不同用户使用不同的权限,锁文件,可设置不同用户使用不同的权限
  • 互斥锁、自旋锁、读写锁和文件锁

    千次阅读 2022-02-28 15:51:06
    互斥锁、自旋锁、读写锁和文件锁互斥锁自旋锁自旋锁与互斥锁之间的区别读写锁文件锁乐观锁与悲观锁举个例子服务端是如何解决这种冲突的 互斥锁 互斥锁(mutex)又叫互斥量,从本质上说是一把锁,在访问共享资源之前...

    互斥锁

    互斥锁(mutex)又叫互斥量,从本质上说是一把锁,在访问共享资源之前对互斥锁进行上锁,在访问完成后释放互斥锁(解锁);对互斥锁进行上锁之后,任何其它试图再次对互斥锁进行加锁的线程都会被阻塞,直到当前线程释放互斥锁。如果释放互斥锁时有一个以上的线程阻塞,那么这些阻塞的线程会被唤醒,它们都会尝试对互斥锁进行加锁,当有一个线程成功对互斥锁上锁之后,其它线程就不能再次上锁了,只能再次陷入阻塞,等待下一次解锁。

    在我们的程序设计当中,只有将所有线程访问共享资源都设计成相同的数据访问规则,互斥锁才能正常工作。如果允许其中的某个线程在没有得到锁的情况下也可以访问共享资源,那么即使其它的线程在使用共享资源前都申请锁,也还是会出现数据不一致的问题。互斥锁使用 pthread_mutex_t 数据类型表示,在使用互斥锁之前,必须首先对它进行初始化操作。

    自旋锁

    自旋锁与互斥锁很相似,从本质上说也是一把锁,在访问共享资源之前对自旋锁进行上锁,在访问完成后释放自旋锁(解锁);事实上,从实现方式上来说,互斥锁是基于自旋锁来实现的,所以自旋锁相较于互斥锁更加底层。

    如果在获取自旋锁时,自旋锁处于未锁定状态,那么将立即获得锁(对自旋锁上锁);如果在获取自旋锁时,自旋锁已经处于锁定状态了,那么获取锁操作将会在原地“自旋”,直到该自旋锁的持有者释放了锁。由此介绍可知,自旋锁与互斥锁相似,但是互斥锁在无法获取到锁时会让线程陷入阻塞等待状态;而自旋锁在无法获取到锁时,将会在原地“自旋”等待。“自旋”其实就是调用者一直在循环查看该自旋锁的持有者是否已经释放了锁,“自旋”一词因此得名。

    自旋锁的不足之处在于:自旋锁一直占用的 CPU,它在未获得锁的情况下,一直处于运行状态(自旋),所以占着 CPU,如果不能在很短的时间内获取锁,这无疑会使 CPU 效率降低。

    试图对同一自旋锁加锁两次必然会导致死锁,而试图对同一互斥锁加锁两次不一定会导致死锁,原因在于互斥锁有不同的类型,当设置为PTHREAD_MUTEX_ERRORCHECK 类型时,会进行错误检查,第二次加锁会返回错误,所以不会进入死锁状态。

    因此我们要谨慎使用自旋锁,自旋锁通常用于以下情况:需要保护的代码段执行时间很短,这样就会使得持有锁的线程会很快释放锁,而“自旋”等待的线程也只需等待很短的时间;在这种情况下就比较适合使用自旋锁,效率高!

    自旋锁与互斥锁之间的区别

    • 实现方式上的区别:互斥锁是基于自旋锁而实现的,所以自旋锁相较于互斥锁更加底层;
    • 开销上的区别:获取不到互斥锁会陷入阻塞状态(休眠),直到获取到锁时被唤醒;而获取不到自旋锁会在原地“自旋”,直到获取到锁;休眠与唤醒开销是很大的,所以互斥锁的开销要远高于自旋锁、自旋锁的效率远高于互斥锁;但如果长时间的“自旋”等待,会使得 CPU 使用效率降低,故自旋锁不适用于等待时间比较长的情况。
    • 使用场景的区别:自旋锁在用户态应用程序中使用的比较少,通常在内核代码中使用比较多;因为自旋锁可以在中断服务函数中使用,而互斥锁则不行,在执行中断服务函数时要求不能休眠、不能被抢占(内核中使用自旋锁会自动禁止抢占),一旦休眠意味着执行中断服务函数时主动交出了CPU使用权,休眠结束时无法返回到中断服务函数中,这样就会导致死锁!
    • 最底层的两种就是「互斥锁和自旋锁」,有很多高级的锁都是基于它们实现,可以认为它们是各种锁的地基,所以得清楚它俩之间的区别和应用。加锁的目的是保证共享资源在任意时间里,只有一个线程访问,这样就可以避免多线程导致共享数据错乱的问题。当已经有一个线程加锁后,其他线程加锁则会失败,互斥锁和自旋锁对于加锁失败后的处理方式是不一样的。

    读写锁

    互斥锁或自旋锁要么是加锁状态、要么是不加锁状态,而且一次只有一个线程可以对其加锁。读写锁有3 种状态:读模式下的加锁状态(以下简称读加锁状态)、写模式下的加锁状态(以下简称写加锁状态)和不加锁状态(见),一次只有一个线程可以占有写模式的读写锁,但是可以有多个线程同时占有读模式的读写锁。因此可知,读写锁比互斥锁具有更高的并行性!
    在这里插入图片描述
    读写锁有如下两个规则:

    • 当读写锁处于写加锁状态时,在这个锁被解锁之前,所有试图对这个锁进行加锁操作(不管是以读模式加锁还是以写模式加锁)的线程都会被阻塞。
    • 当读写锁处于读加锁状态时,所有试图以读模式对它进行加锁的线程都可以加锁成功;但是任何以写模式对它进行加锁的线程都会被阻塞,直到所有持有读模式锁的线程释放它们的锁为止。

    虽然各操作系统对读写锁的实现各不相同,但当读写锁处于读模式加锁状态,而这时有一个线程试图以写模式获取锁时,该线程会被阻塞;而如果另一线程以读模式获取锁,则会成功获取到锁,对共享资源进行读操作。

    所以,读写锁非常适合于对共享数据读的次数远大于写的次数的情况。当读写锁处于写模式加锁状态时,它所保护的数据可以被安全的修改,因为一次只有一个线程可以在写模式下拥有这个锁;当读写锁处于读模式加锁状态时,它所保护的数据就可以被多个获取读模式锁的线程读取。所以在应用程序当中,使用读写锁实现线程同步,当线程需要对共享数据进行读操作时,需要先获取读模式锁(对读模式锁进行加锁),当读取操作完成之后再释放读模式锁(对读模式锁进行解锁);当线程需要对共享数据进行写操作时,需要先获取到写模式锁,当写操作完成之后再释放写模式锁。

    读写锁也叫做共享互斥锁。当读写锁是读模式锁住时,就可以说成是共享模式锁住。当它是写模式锁住时,就可以说成是互斥模式锁住。

    文件锁

    现象一下,当两个人同时编辑磁盘中同一份文件时,其后果将会如何呢?在 Linux 系统中,该文件的最后状态通常取决于写该文件的最后一个进程。多个进程同时操作同一文件,很容易导致文件中的数据发生混乱,因为多个进程对文件进行 I/O 操作时,容易产生竞争状态、导致文件中的内容与预想的不一致!

    对于有些应用程序,进程有时需要确保只有它自己能够对某一文件进行 I/O 操作,在这段时间内不允许其它进程对该文件进行 I/O 操作。为了向进程提供这种功能,Linux 系统提供了文件锁机制。

    前面学习过互斥锁、自旋锁以及读写锁,文件锁与这些锁一样,都是内核提供的锁机制,锁机制实现用于对共享资源的访问进行保护;只不过互斥锁、自旋锁、读写锁与文件锁的应用场景不一样,互斥锁、自旋锁、读写锁主要用在多线程环境下,对共享资源的访问进行保护,做到线程同步。

    而文件锁,顾名思义是一种应用于文件的锁机制,当多个进程同时操作同一文件时,我们怎么保证文件数据的正确性,linux 通常采用的方法是对文件上锁,来避免多个进程同时操作同一文件时产生竞争状态。譬如进程对文件进行 I/O 操作时,首先对文件进行上锁,将其锁住,然后再进行读写操作;只要进程没有对文件进行解锁,那么其它的进程将无法对其进行操作;这样就可以保证,文件被锁住期间,只有它(该进程)可以对其进行读写操作。

    一个文件既然可以被多个进程同时操作,那说明文件必然是一种共享资源,所以由此可知,归根结底,文件锁也是一种用于对共享资源的访问进行保护的机制,通过对文件上锁,来避免访问共享资源产生竞争状态

    乐观锁与悲观锁

    前面提到的互斥锁、自旋锁、读写锁,都是属于悲观锁。悲观锁做事比较悲观,它认为多线程同时修改共享资源的概率比较高,于是很容易出现冲突,所以访问共享资源前,先要上锁。

    相反的,如果多线程同时修改共享资源的概率比较低,就可以采用乐观锁。乐观锁做事比较乐观,它假定冲突的概率很低,它的工作方式是:先修改完共享资源,再验证这段时间内有没有发生冲突,如果没有其他线程在修改资源,那么操作完成,如果发现有其他线程已经修改过这个资源,就放弃本次操作。

    放弃后如何重试,这跟业务场景息息相关,虽然重试的成本很高,但是冲突的概率足够低的话,还是可以接受的。可见,乐观锁的心态是,不管三七二十一,先改了资源再说。另外,你会发现乐观锁全程并没有加锁,所以它也叫无锁编程。

    举个例子

    在线文档是可以同时多人编辑,如果使用了悲观锁,只要有一个用户正在编辑文档,此时其他用户就无法打开相同的文档,用户体验当然不好。

    实现多人同时编辑,实际上是用了乐观锁,它允许多个用户打开同一个文档进行编辑,编辑完提交之后才验证修改的内容是否有冲突。

    怎么样才算发生冲突?这里举个例子,比如用户 A 先在浏览器编辑文档,之后用户 B 在浏览器也打开了相同的文档进行编辑,但是用户 B 比用户 A 提交改动,这一过程用户 A 是不知道的,当 A 提交修改完的内容时,那么 A 和 B 之间并行修改的地方就会发生冲突。

    服务端是如何解决这种冲突的

    由于发生冲突的概率比较低,所以先让用户编辑文档,但是浏览器在下载文档时会记录下服务端返回的文档版本号;当用户提交修改时,发给服务端的请求会带上原始文档版本号,服务器收到后将它与当前版本号进行比较,如果版本号一致则修改成功,否则提交失败。

    实际上,常见的 SVN 和 Git 也是用了乐观锁的思想,先让用户编辑代码,然后提交的时候,通过版本号来判断是否产生了冲突,发生了冲突的地方,需要我们自己修改后,再重新提交。

    乐观锁虽然去除了加锁解锁的操作,但一旦发生冲突,重试的成本非常高,所以只有在冲突概率非常低,且加锁成本非常高的场景时,才考虑使用乐观锁。

    总结

    互斥锁、自旋锁和读写锁用于解决多线程同步的问题

    文件锁适用于多个进程同时操作同一文件,这时很容易导致文件中的数据发生混乱

    展开全文
  • 文件锁

    2011-11-11 19:58:32
    文件锁,一款关于文件的锁,很实用的哦。它虽然不大,但是功能强大,用过都说好
  • 文件锁(二)——文件锁的读锁和写锁

    千次阅读 2022-03-28 20:14:49
    文件锁的读锁和写锁 对文件加锁时可以加两种锁,分别是“读文件锁”和“写文件锁”,简称读锁和写锁。 读锁、写锁之间关系 读锁和读锁共享:可以重复加读锁,别人加了读锁在没有解锁之前,我依然可以加读锁,这...

    文件锁的读锁和写锁

    对文件加锁时可以加两种锁,分别是“读文件锁”和“写文件锁”,简称读锁和写锁。

    读锁、写锁之间关系

    1. 读锁和读锁共享:可以重复加读锁,别人加了读锁在没有解锁之前,我依然可以加读锁,这就是共享。
    2. 读锁和写锁互斥:别人加了读锁没解锁前,加写锁会失败,反过来也是如此。
      • 加锁失败后两种处理方式:
        • 阻塞,直到别人解锁然后加锁成功为止。
        • 出错返回,不阻塞
    3. 写锁与写锁互斥:别人加了写锁在没有解锁前,不能加写锁,加写锁会失败。
      • 加锁失败后两种处理方式:

        • 阻塞,直到别人解锁然后加锁成功为止
        • 出错返回,不阻塞

    文件的加锁方式

    1. 对整个文件的内容加锁
      对整个文件加锁是最常用的文件加锁方式。
      当你整个文件加锁时,如果文件的长度因为写入新数据或者截短而发生了变化,加锁内容长度会自动变化,保证对内容变化着的整个文件加锁。

    2. 对文件某部分内容加锁

      不过一般来说,对多少内容加锁,就对多少内容解锁。如果你是对整个文件加锁,就将整个文件解锁。

      但是实际上加锁和实际解锁的长度不相同,比如我对1000个字节的内容加了锁,但是只对其中的100字节解锁,不过这种情况用的少,知道怎么回事即可。

      怎么实现文件的整个加锁和区域解锁呢?

      后面再说

    3.  

    再看看fcntl的函数原型

    int fcntl(int fd, int cmd, ... /* struct flock *flockptr */ );

    第三个参数是...,fcntl函数是一个变参函数,第三个参数用不到时就不写

    1. 功能
      fcntl函数有多种功能,我们这里主要介绍实现文件锁的功能,当cmd被设置的是与文件锁相关的宏时,fcntl就是用来实现文件锁。
    2. 参数
      • fd:文件描述符,指向所需要被加锁的文件
      • cmd:实现文件锁时,cmd有三种设置,F_GETLK,F_SETLK和F_SETLKW含义如下:
        1. F_GETLK
          从内核获取文件锁的信息,将其保存到第三个参数,第三个参数struct flock *flockptr,我们这里是要设置文件锁,而不是获取已有的文件锁信息,我们这里用不到这个宏。
        2. F_SETLK
          设置第三个参数所代表的文件锁,而且设置的是非阻塞文件锁,也就是如果加锁失败不会阻塞。也就是说加锁失败后如果不想阻塞的话,就由F_SETLK宏来设置。
          此时,需要用到第三个参数:struct flock *flockptr;
          使用举例:
          1. 第一步:定义一个struct flock flockptr结构体变量(这个结构体变量就是文件锁)。
          2. 第二步:设置flockptr的成员,表示你想设置怎样的文件锁
          3. 第三步:通过第三个参数,将设置好的flockptr的地址传递给fcntl,设置你想要的文件锁
        3. F_SETLKW
          F_SETLKW一样,只不过设置的是阻塞文件锁,也就是说加锁不成功的话就阻塞,是由F_SETLKW宏来决定的。
    3. int fcntl(int fd, int cmd, ... /* struct flock *flockptr */ );
      • 第三个参数
        • 第三个参数设置为什么视情况而定,如果fcntl用于实现文件锁的话,第三个参数为struct flock *flockptr,flockptr代表的就是文件锁。
        • 对flockptr的成员设置为特定的值,就可以将文件锁设置为你想要的锁。
        • struct flock结构体如下:
           struct flock {
                         ...
                         short l_type;    /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */
                         short l_whence;  /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
                         off_t l_start;   /* Starting offset for lock */
                         off_t l_len;     /* Number of bytes to lock */
                         pid_t l_pid;     /* PID of process blocking our lock
                                             (set by F_GETLK and F_OFD_GETLK) */
                         ...
          };
          
          

    成员说明:

    • l_type:锁类型

      • F_RDLCK:读锁(或称共享锁)
      • F_WRLCK:写锁
      • F_UNLCK:解锁
    • l_whence:加锁位置粗定位,设置同lseek的whence

      • SEEK_SET:文件开始处
      • SEEK_CUR:文件当前位置处
      • SEEK_END:文件末尾位置处
      • l_whence这个与lseek函数的whence是一个含义
    • l_start:精定位,相对于l_whence的偏移,与lseek的offset的含义完全一致
      通过l_whence和l_start的值,就可以用来指定从文件的什么位置开始加锁,不过一般来说,我们会将l_whence指定为SEEK_SET,l_start指定为0,表示从整个文件头上开始加锁。

    • l_len:从l_whence和l_start所指定的起始地点算起,需要对文件多长的内容加锁。

      如果 l_len被设置0,表示一直加锁到文件结尾,如果文件长度时变化的,将自动调整加锁的末尾位置

      l_whence和l_start设置为SEEK_SET和0,然后再将l_len设置为0,就表示从文件加锁到文件末尾,其实就是对整个文件加锁。

      如果只是对文件中间的某段加锁,这只是区域加锁,加区域锁时可以给文件n多个的独立区域加锁。

    • l_pid:当前正加锁进程的PID

    代码演示

    使用文件锁的互斥操作,解决父子进程向同一文件写"hello",“world\n”时,hello hello world相连的问题。

    头文件,学到了封装函数的思想,尤其是使用宏来实现不同类型的文件锁

    /* Too many parameters ,Different types of locks
     * Write dead!!!!!!!!!
     * */
    /* Set non blocking write lock */
    #define SET_WRFLCK(fd, l_whence, l_start, l_len) \
    		set_filelock(fd, F_SETLK, F_WRLCK, l_whence, l_start, l_len)
    
    /* Set blocking write lock */
    #define SET_WRFLCKW(fd, l_whence, l_start, l_len) \
    		set_filelock(fd, F_SETLKW, F_WRLCK, l_whence, l_start, l_len)
    
    /* Set blocking read lock */
    #define SET_RDFLCKW(fd, l_whence, l_start, l_len) \
    		set_filelock(fd, F_SETLKW, F_RDLCK, l_whence, l_start, l_len)
    
    /* Set nonblocking read lock */
    #define SET_RDFLCK(fd, l_whence, l_start, l_len) \
    		set_filelock(fd, F_SETLK, F_RDLCK, l_whence, l_start, l_len)
    
    /* Unlock */
    #define SET_UNFLCK(fd, l_whence, l_start, l_len) \
    		set_filelock(fd, F_SETLK, F_UNLCK, l_whence, l_start, l_len)
    
    /*Package and set the locking function
     * */
    static void set_filelock(int fd, int ifwait, short l_type, short l_whence, off_t l_start, short l_len) 
    {
    	int ret = 0;
    	struct flock flock;
    
    	flock.l_type = l_type;
    	flock.l_whence = l_whence;
    	flock.l_start = l_start;
    	flock.l_len = l_len;
    
    	ret = fcntl(fd, ifwait, &flock);
    	if (ret == -1)
    	{
    		perror("fcntl");
    		exit(EXIT_FAILURE);
    	}
    }
    
    
    int main(int argc, char *argv[])
    {
    	int fd = 0;
    	int ret = 0;
    
    	fd = open("./hello", O_RDWR|O_CREAT|O_TRUNC, 0664);
    	if (fd == -1)  print_err("./hello", __LINE__, errno); 
    
    	ret = fork();
    	if (ret > 0)
    	{
    		while(1)
    		{
    			SET_WRFLCKW(fd, SEEK_SET, 0, 0);
    			write(fd, "hello ", 6);
    			write(fd, "world\n", 6);
    			SET_UNFLCK(fd, SEEK_SET, 0, 0);
    		}
    	}
    	else if (ret == 0)
    	{
    		while(1)
    		{
    			SET_WRFLCKW(fd, SEEK_SET, 0, 0);
    			write(fd, "hello ", 6);
    			write(fd, "world\n", 6);
    			SET_UNFLCK(fd, SEEK_SET, 0, 0);
    		}
    	}
    	return 0;
    }
    
    

    在hello文件里面使用/hello hello没找到文本内容说明成功了。

    对于fcntl的认识不仅仅可以追加改变文件标志,还可以实现文件锁的功能

    展开全文
  • python文件锁

    千次阅读 2021-11-16 22:56:21
    python文件锁

    一个lock file的python
    实现

    此代码基于实际业务出发,且已应用于线上生产环境(已脱敏)

    需求背景:python脚本项目,实现同一个脚本不能同时执行,需要在具体的脚本执行前加锁控制

    需求实现方案:

            1.基于文件的python的文件锁

            2.基于端口号的端口锁(已测试在并发环境下锁不住)

    python文件锁实现方案:

            如果多个进程,或者多个独立程序要写同一个文件,那么就存在大家同时写文件的可能,这时就需要具体的脚本执行前加锁,控制并发
    文件名:lockfile.py

    import os
    import time
    import errno
     
    class FileLockException(Exception):
        pass
     
    class FileLock(object):
     
        def __init__(self, file_name, timeout=10, delay=.05):
           
            self.is_locked = False
            # 将锁文件放置统一位置,方便管理
            dirs = sys.path[0] + "/lock"
            if not os.path.exists(dirs):
                os.makedirs(dirs)
            self.lockfile = os.path.join(dirs, "%s.lock" % file_name)
            self.file_name = file_name
            self.timeout = timeout
            self.delay = delay
     
     
        def acquire(self):
            start_time = time.time()
            while True:
                try:
                    #独占式打开文件
                    #os.O_RDWR : 以读写的方式打开
                    #os.O_CREAT: 创建并打开一个新文件
                    #os.O_EXCL: 如果指定的文件存在,返回错误
                    self.fd = os.open(self.lockfile, os.O_CREAT|os.O_EXCL|os.O_RDWR)
                    break;
                except OSError as e:
                    if e.errno != errno.EEXIST:
                        raise 
                    if (time.time() - start_time) >= self.timeout:
                        raise FileLockException("Timeout occured.")
                    time.sleep(self.delay)
            self.is_locked = True
     
     
        def release(self):
            #关闭文件,删除文件
            if self.is_locked:
                os.close(self.fd)
                os.unlink(self.lockfile)
                self.is_locked = False
     
     
        def __enter__(self):
            if not self.is_locked:
                self.acquire()
            return self
     
     
        def __exit__(self, type, value, traceback):
            if self.is_locked:
                self.release()
     
     
        def __del__(self):
            self.release()
     

    测试类test_lock.py

    def test_lock(i):
        with FileLock('myfile.txt', 2):
            print("%s get lock success, %s" % (str(i), str(time.time())))
            time.sleep(3)
    
    
    if __name__ == '__main__':
        for i in range(5):
            threading.Thread(target=test_lock, args={i}).start()
        time.sleep(5)

    用法比较有意思,使用with关键字。对with关键字来说,FileLock类先执行__enter__函数,然后,执行with块里的那些代码,执行完了之后,再执行__exit__函数,等价于相当于如下形式:

    try:
          执行 __enter__的内容
          执行 with_block.
    finally:
          执行 __exit__内容


    FileLock在__enter__函数独占式创建或打开一个文件,这个文件不会被其他程序或者进程再次创建或者打开,由此形成lock,执行完代码,在__exit__里,关闭并删除文件

    后续测试内容需补充

    文章借鉴:python lockfile(文件锁)一个lock file的python实现如果多个进程,或者多个独立程序要写同一个文件,那么就存在大家同时写文件的可能,这就不妙了,数据可能会出问题。最近在网上找到一个开源的python实现,有效简洁,列出来分析下代码看看:文件名:lockfile.py,内容如下,有部分注释加了中文,添加了一些注释。import osimport timeimport errno classhttps://blog.csdn.net/rubbishcan/article/details/17352261

    展开全文
  • 文件锁(一)——文件锁的概述

    千次阅读 2022-03-28 00:33:17
    文件锁的概述 文件锁也被称为记录锁,文件锁如果深耕的话,意义不大(比如文件锁起码分为了建议锁和强制性锁)。 但是深入没有意义的,因为实际开发很少用上,文件锁用到的机会不多,那为什么要学? 主要是为了对比...
  • linux 文件锁

    千次阅读 2021-02-17 21:20:13
    1. 文件锁基本概念 Linux中软件、硬件资源都是文件(一切皆文件),文件在多用户环境中是可共享的。 文件锁是用于解决资源的共享使用的一种机制:当多个用户需要共享一个文件时,Linux通常采用的方法是给文件上锁,...
  • linux文件锁flock

    2015-09-29 09:35:37
    linux文件锁flock
  • 简单谈谈 php 文件锁

    2020-10-20 09:12:45
    PHP出现文件锁与mysql表锁有大概想的用法,就是同一时间只能让一个人操作,这样就避免了同时有多个人操作同一文件,这样导致数据丢失的情况了,下面我来给大家介绍PHP文件锁用法。
  • 为了解决并发对文件IO操作的影响,这样就出现了文件锁,多个进程如果在没有设置文件锁的情况下是可以访问同一个文件的,比如我一个进程已经开始写这个文件了,那么另外一个进程也可以写,那这样不就乱套了吗,文件锁...
  • Java文件锁

    2021-09-20 22:07:28
    共享防止其他正在运行的程序获得重复的独占,但是允许他们获得重复的共享。 独占: 只有一个读或一个写(读和写都不能同时)。独占防止其他程序获得任何类型的。 二、FileLock ...
  • golang下文件锁的使用

    千次阅读 2020-12-04 02:38:20
    题目是golang下文件锁的使用,但本文的目的其实是通过golang下的文件锁的使用方法,来一窥文件锁背后的机制。 为什么需要文件锁 只有多线程/多进程这种并发场景下读写文件,才需要加锁, 场景1-读写并发 读写并发...
  • 本篇文章主要介绍了PHP 文件锁与进程锁的使用示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 详解进程文件锁FileLock

    千次阅读 2020-12-11 12:43:46
    } } } } } /** * 间隔一秒钟两次运行本程序,程序会在文件锁的控制下对logfile.txt进行互斥操作 logfile.txt内容: Thu Aug 16 15:39:02 CST 2012 写入 Thu Aug 16 15:39:07 CST 2012 写入 当采用第二种方法时,若...
  • C语言文件锁的实现

    千次阅读 2021-07-30 15:37:13
    c语言文件锁的实现
  • 主要介绍了PHP程序中的文件锁、互斥锁、读写锁使用技巧解析,其中重点讲解了sync模块和pthreads模块中的使用实例,需要的朋友可以参考下
  • Ubuntu解决文件带锁问题

    千次阅读 2022-04-01 19:42:31
    Ubuntu解决文件带锁问题在使用Ubuntu过程中发现文件带锁,记录一下解决方法 在使用Ubuntu过程中发现文件带锁,记录一下解决方法 1.解锁当前路径下的单个文件 sudo chmod 777 filename 2.解锁当前路径下的所有文件夹...
  • 这里的进程锁与线程锁、互斥锁、读写锁和自旋锁不同,它是通过记录一个PID文件,避免两个进程同时运行的文件锁。 进程锁的作用之一就是可以协调进程的运行,例如crontab使用进程锁解决冲突提到,使用crontab限定每...
  • qt程序进程单例(文件锁的方法) 原理 通过锁定文件,直至程序退出解锁,那么当程序第二次打开的时候检测到文件是锁定的,则退出 使用qt文件锁的方法 请在main函数里面使用,不要单独封装函数,保证锁没有退出,因为...
  • 在linux下实现守护进程并加上排它锁(文件锁),避免重复启动进程
  • Python使用fcntl文件锁

    千次阅读 2020-08-04 09:52:19
    Python语言中的文件锁可以使用 fcntl 库,它实际上是对Unix系统上的 fcntl 和 ioctl 函数提供了一个接口。官网描述中是这样形容的: This module performs file control and I/O control on file descriptors 这个...
  • Linux 文件锁 . LCK文件

    千次阅读 2021-10-22 10:59:44
    锁文件(.lck)是由某些应用程序和操作系统自动创建的小型服务文件,用于用户当前主动打开的任何用户文件。 锁定文件(.lck)的目的是标记用户文件(通常是数据库)的 "繁忙 "状态,以避免在多用户和多任务环境中数据丢失...
  • 文件锁代码

    2012-08-08 11:07:12
    文件锁功能实现
  • Linux flock文件锁详解

    千次阅读 2020-11-25 23:30:34
    -h --help Display this text #显示帮助 -V --version Display version #显示版本 flock文件锁的使用 1.创建sh文件 vim test.sh #! /bin/bash echo "Hello World" sleep 10 2.创建锁文件 touch test.lock #随便命名 ...
  • 在linux系统下如何给文件解锁

    千次阅读 2021-04-26 16:26:16
    使用代码:sudo chmod -R 777 【文件路径】我使用代码:sudo chmod -R 777 ~/go (~/go表示在主文件下的go文件夹)sudo chmod -R 777 $GOPATH (表示将gopath路径下的文件夹全部解锁)我们可以看到go文件夹的已经...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 625,135
精华内容 250,054
关键字:

文件锁