精华内容
下载资源
问答
  • linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。 对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。 其中,参数 fd 表示文件描述...
  • 使用fcntl在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。其中...

    Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对文件的读写操作。在管理多个线程对同一文件的读写操作时,就少不了文件锁了。

    使用fcntl

    在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。

    对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。

    其中,参数 fd 表示文件描述符;参数 operation 指定要进行的锁操作,该参数的取值有如下几种:

    LOCK_SH:表示要创建一个共享锁,在任意时间内,一个文件的共享锁可以被多个进程拥有

    LOCK_EX:表示创建一个排他锁,在任意时间内,一个文件的排他锁只能被一个进程拥有

    LOCK_UN:表示删除该进程创建的锁

    LOCK_MAND:它主要是用于共享模式强制锁,它可以与 LOCK_READ 或者 LOCK_WRITE联合起来使用,从而表示是否允许并发的读操作或者并发的写操作

    demo

    import fcntl

    import threading

    import time

    def writetoTxt(txtFile):

    id = threading.currentThread().getName()

    with open(txtFile, 'a') as f:

    fcntl.flock(f.fileno(), fcntl.LOCK_EX) #加锁

    print "{0} acquire lock".format(id)

    f.write("write from {0} \r\n".format(id))

    time.sleep(3)

    # 在with块外,文件关闭,自动解锁

    print "{0} exit".format(id)

    for i in range(5):

    myThread = threading.Thread(target=writetoTxt, args=("test.txt",))

    myThread.start()

    代码运行期间,控制台将依次打印哪个线程获得了锁,在对文件进行读写。

    Thread-1 acquire lock

    Thread-1 exit

    Thread-2 acquire lock

    Thread-2 exit

    Thread-3 acquire lock

    Thread-3 exit

    Thread-5 acquire lock

    Thread-5 exit

    Thread-4 acquire lock

    Thread-4 exit

    小结

    通过调用

    fcntl.flock(f.fileno(), fcntl.LOCK_EX)

    对文件加锁,如果有其他线程尝试对test文件加锁,会被阻塞。

    当线程执行完毕的时候,锁会自动释放。或者也可以采取主动的方式解锁:调用

    fcntl.flock(f.fileno(),fcntl.LOCK_UN)

    函数, 对文件test解锁

    使用线程锁

    当多个线程共享一个数据的时候,必须要进行同步的控制,不然会出现不可预期的结果,即 “线程不安全”

    线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。

    互斥锁为资源引入一个状态:锁定/非锁定。

    某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;

    直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。

    互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

    threading模块中定义了Lock类,可以方便的处理锁定:

    #创建锁

    mutex = threading.Lock()

    #锁定

    mutex.acquire([timeout])

    #解锁

    mutex.release()

    Demo

    使用互斥锁实现上面的例子的代码如下:

    import threading

    import time

    def writetoTxt(txtFile):

    id = threading.currentThread().getName()

    mutex.acquire(10)

    with open(txtFile, 'a') as f:

    print "Thread {0} acquire lock".format(id)

    f.write("write from thread {0} \r\n".format(id))

    time.sleep(3)

    mutex.release()

    print "Thread {0} exit".format(id)

    mutex = threading.Lock()

    for i in range(5):

    myThread = threading.Thread(target=writetoTxt, args=("test.txt",))

    myThread.start()

    (上述代码本质上是一个顺序执行的单线程)

    结果:

    Thread Thread-1 acquire lock

    Thread Thread-1 exit

    Thread Thread-2 acquire lock

    Thread Thread-2 exit

    Thread Thread-3 acquire lock

    Thread Thread-3 exit

    Thread Thread-4 acquire lock

    Thread Thread-4 exit

    Thread Thread-5 acquire lock

    Thread Thread-5 exit

    小结

    当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”。

    直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

    以上这篇对Python多线程读写文件加锁的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

    展开全文
  • Python多线程读写文件加锁

    千次阅读 2018-11-16 10:11:03
    Python的多线程在io方面比单线程...在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。 对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这...

    Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对文件的读写操作。在管理多个线程对同一文件的读写操作时,就少不了文件锁了。

    使用fcntl

    在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。

    对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。

    其中,参数 fd 表示文件描述符;参数 operation 指定要进行的锁操作,该参数的取值有如下几种:

    • LOCK_SH:表示要创建一个共享锁,在任意时间内,一个文件的共享锁可以被多个进程拥有
    • LOCK_EX:表示创建一个排他锁,在任意时间内,一个文件的排他锁只能被一个进程拥有
    • LOCK_UN:表示删除该进程创建的锁
    • LOCK_MAND:它主要是用于共享模式强制锁,它可以与 LOCK_READ 或者 LOCK_WRITE联合起来使用,从而表示是否允许并发的读操作或者并发的写操作

    demo

    import fcntl
    import threading
    import time
    
    
    def writetoTxt(txtFile):
        id = threading.currentThread().getName()
        with open(txtFile, 'a') as f:
            fcntl.flock(f.fileno(), fcntl.LOCK_EX) #加锁
            print "{0} acquire lock".format(id)
            f.write("write from {0} \r\n".format(id))
            time.sleep(3)
        # 在with块外,文件关闭,自动解锁
        print "{0} exit".format(id)
    
    
    for i in range(5):
        myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
        myThread.start()
    

    代码运行期间,控制台将依次打印哪个线程获得了锁,在对文件进行读写。

    Thread-1 acquire lock
    Thread-1 exit
    Thread-2 acquire lock
    Thread-2 exit
    Thread-3 acquire lock
    Thread-3 exit
    Thread-5 acquire lock
    Thread-5 exit
    Thread-4 acquire lock
    Thread-4 exit

    小结

    通过调用

    fcntl.flock(f.fileno(), fcntl.LOCK_EX)
    

    对文件加锁,如果有其他线程尝试对test文件加锁,会被阻塞。

    当线程执行完毕的时候,锁会自动释放。或者也可以采取主动的方式解锁:调用

    fcntl.flock(f.fileno(),fcntl.LOCK_UN)
    

    函数, 对文件test解锁

    使用线程锁

    当多个线程共享一个数据的时候,必须要进行同步的控制,不然会出现不可预期的结果,即 “线程不安全”

    线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。
    互斥锁为资源引入一个状态:锁定/非锁定。
    某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;
    直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。
    互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
    

    threading模块中定义了Lock类,可以方便的处理锁定:

    #创建锁
    mutex = threading.Lock()
    #锁定
    mutex.acquire([timeout])
    #解锁
    mutex.release()
    

    Demo

    使用互斥锁实现上面的例子的代码如下:

    import threading
    import time
    
    def writetoTxt(txtFile):
        id = threading.currentThread().getName()
        mutex.acquire(10)
        with open(txtFile, 'a') as f:
            print "Thread {0} acquire lock".format(id)
            f.write("write from thread {0} \r\n".format(id))
            time.sleep(3)
        mutex.release()
        print "Thread {0} exit".format(id)
    
    
    mutex = threading.Lock()
    
    for i in range(5):
        myThread = threading.Thread(target=writetoTxt, args=("test.txt",))
        myThread.start()
    

    (上述代码本质上是一个顺序执行的单线程)

    结果:

    Thread Thread-1 acquire lock
    Thread Thread-1 exit
    Thread Thread-2 acquire lock
    Thread Thread-2 exit
    Thread Thread-3 acquire lock
    Thread Thread-3 exit
    Thread Thread-4 acquire lock
    Thread Thread-4 exit
    Thread Thread-5 acquire lock
    Thread Thread-5 exit
    

    小结

    当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”。
    直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

     

    展开全文
  • Linux文件加锁

    千次阅读 2019-12-22 22:12:36
    在较老的不支持文件加锁的 UNIX 实现上,可以是会用一些特别的加锁技术。尽管这些技术都已经被 fcntl() 记录加锁计数所取代,但这里仍然需要介绍它们,因为一些较早的应用程序中,仍然存在他们的身影。所有的这些...

    /proc/locks

    andrew@andrew-Thurley:/dev$ cat /proc/locks 
    1: POSIX  ADVISORY  WRITE 8968 08:01:11666907 1073741825 1073741825
    2: POSIX  ADVISORY  READ  2433 08:01:11798469 128 128
    ...
    35: FLOCK  ADVISORY  WRITE 1436 00:1a:7 0 EOF
    51: FLOCK  ADVISORY  WRITE 1036 00:16:763 0 EOF
    
    

    使用ps -p PID查看进程的相关信息

    andrew@andrew-Thurley:/dev$ ps -p 8968
      PID TTY          TIME CMD
     8968 ?        00:00:02 chrome
    

    从上面的输出可以看出持有的锁的程序是chrome,即 google浏览器

    /dev我下搜索主设备号为8次设备号为1的设备,是/dev/sda1

    andrew@andrew-Thurley:/dev$ ls -li /dev/sda1 |awk '$6=8'
    351 brw-rw---- 1 root disk 8 1 12月 22 13:13 /dev/sda1
    

    查看设备/dev/sda1的挂载点,并在该部分文件系统中搜索i-node节点为11666907的文件

    andrew@andrew-Thurley:/dev$ mount |grep sda1
    /dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
    

    从上面的输出可以看出,设备/dev/sda1是挂在在 /上的

    andrew@andrew-Thurley:/dev$ sudo find / -mount -inum 11666907
    /home/andrew/.config/google-chrome/Default/History
    

    find -mount选项是防止find进入到/下的子目录进行搜索

    最后显示被锁住文件的内容--google浏览器的历史记录

    sudo vim /home/andrew/.config/google-chrome/Default/History

    是一个google浏览器的SQLite数据库文件

    在这里插入图片描述

    这样就可以看出google浏览器持有文件sudo vim /home/andrew/.config/google-chrome/Default/History上的一把锁,而这个文件的内容就是google用于记录历史记录的数据库文件。

    通过/proc/locks还能够获取被阻塞的锁请求的相关信息,如下图所示

    在这里插入图片描述

    其中锁号后面随即跟着->的行表示被阻塞的锁的请求

    仅运行一个程序的单个实例

    一些程序-特别是很多的daemon需要确保同一时刻只有一个程序实例在系统中运行。完成这项任务的一个常见的方法是让daemon在一个标准的目录中创建一个文件并在该文件上放置一把写锁。daemon在执行期间一直持有这个文件锁并在即将终止前删除这个文件。如果启用了daemon的另外一个实例,那么它在获取该文件的写锁时就会失败,其结果是它会意识到daemon的另一个实例肯定在运行,然后终止。

    很多的网络服务器采用了另一种常规的做法,即当服务器绑定的众所周知的socket端口号已经被使用时就认为该服务器实例已经处于运行在状态了

    /var/run目录通常是存放此类文件的位置,或者也可以在daemon的配置文件中加上一行,来指定文件的位置。

    通常daemon会将其进程ID写入该文件,因此这个文件命名时通常将.pid作为扩展名。这对于那些需要找出daemon的进程ID的应用程序来讲是比较有用的。它允许执行额外的健全检查--效果可以像20.5节那样使用kill(pid,0)来检查进程ID是否存在。

    文件create_pid_file.c展示了,用来创建和锁住一个进程ID锁文件的代码实现。可以使用下面的方式调用这个函数。

    if(createPidFile("mydaemon", "/car/run/mydaemon.pid", 0) == -1)
    	errExit("createPidFile");
    

    createPidFile函数的精妙之处在于使用ftruncate()函数来清除文件中之前存在的所有的字符串。之所以这样做是因为daemon的上一个实例在删除文件时可能因系统崩溃而失败,在这种情况下,如果新的daemon实例的进程ID较小,那么可能就无法完全覆盖之前文件中的内容,从严格意义上来说清除所有的既有字符串不是必需的,但这样做显得更加简洁并且排除产生混淆的可能。

             
    #include <sys/stat.h>
    #include <fcntl.h>
    #include "region_locking.h"             /* For lockRegion() */
    #include "create_pid_file.h"            /* Declares createPidFile() and
                                                      defines CPF_CLOEXEC */
    #include "tlpi_hdr.h"
    
    #define BUF_SIZE 100            /* Large enough to hold maximum PID as string */
        
    #define CPF_CLOEXEC 1
    static int
    lockReg(int fd, int cmd, int type, int whence, int start, off_t len)
    {
        struct flock fl;
    
        fl.l_type = type;
        fl.l_whence = whence;
        fl.l_start = start;
        fl.l_len = len;
    
        return fcntl(fd, cmd, &fl);
    }
    
    int                     /* Lock a file region using nonblocking F_SETLK */
    lockRegion(int fd, int type, int whence, int start, int len)
    {
        return lockReg(fd, F_SETLK, type, whence, start, len);
    }
    int
    createPidFile(const char *progName, const char *pidFile, int flags)
    {
        int fd;
        char buf[BUF_SIZE];
    
        fd = open(pidFile, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
        if (fd == -1)
            errExit("Could not open PID file %s", pidFile);
    	//< flags 设置为1的时候使用fcntl设置FD_CLOEXEC
        // 对于通过exec()来从起自己的进程比较有用,如果在exec()时文件描述符没有被关闭,那么重新启动的服务器就会认为服务器的另一个示例处于运行状态。
        if (flags & CPF_CLOEXEC) {
    
            /* Set the close-on-exec file descriptor flag */
    
            /* Instead of the following steps, we could (on Linux) have opened the
               file with O_CLOEXEC flag. However, not all systems support open()
               O_CLOEXEC (which was standardized only in SUSv4), so instead we use
               fcntl() to set the close-on-exec flag after opening the file */
    
            flags = fcntl(fd, F_GETFD);                     /* Fetch flags */
            if (flags == -1)
                errExit("Could not get flags for PID file %s", pidFile);
    
            flags |= FD_CLOEXEC;                            /* Turn on FD_CLOEXEC */
    
            if (fcntl(fd, F_SETFD, flags) == -1)            /* Update flags */
                errExit("Could not set flags for PID file %s", pidFile);
        }
    	//设置一把写锁 SEEK_SET-开头  0 到 len=0代表到EOF
        //即对整个文件放置一把写锁,并且写锁的范围随着文件的增加而改变
        if (lockRegion(fd, F_WRLCK, SEEK_SET, 0, 0) == -1) {
            if (errno  == EAGAIN || errno == EACCES)
                fatal("PID file '%s' is locked; probably "
                         "'%s' is already running", pidFile, progName);
            else
                errExit("Unable to lock PID file '%s'", pidFile);
        }
    	//将文件的大小截断为0
        if (ftruncate(fd, 0) == -1)
            errExit("Could not truncate PID file '%s'", pidFile);
    	//将PID写如文件
        snprintf(buf, BUF_SIZE, "%ld\n", (long) getpid());
        if (write(fd, buf, strlen(buf)) != strlen(buf))
            fatal("Writing to PID file '%s'", pidFile);
    
        return fd;
    }
    
    

    老式加锁技术

    在较老的不支持文件加锁的UNIX实现上,可以是会用一些特别的加锁技术。尽管这些技术都已经被fcntl()记录加锁计数所取代,但这里仍然需要介绍它们,因为一些较早的应用程序中,仍然存在他们的身影。所有的这些技术在性质上都是劝告式的

    open(file, O_CREAT | O_EXCL,...)加上unlink(file)

    SUSv3第三版的单一规范里,要求使用了O_CREATO_EXCL标记的open()调用原子执行检查文件的存在性,以及创建文件的两个步骤。这就意味着如果两个进程尝试在创建一个文件时指定这些标记,那么就保证其中只有一个进程能够成功。(另外一个进程从open中收到EEXIST错误。)这种调用与unlink()系统调用组合起来就构成一种加锁机制的基础。获取所可通过使用O_CREATO_EXCL标记打开文件后,立即跟着一个close()来完成,释放锁可通过使用unlink()来完成,尽管这项技术能够正常的工作,但它存在一些局限:

    • 如果open()失败了,即表示其他进程拥有了锁,那么就必须要在某种循环中重试open()操作,这种循环既可以是持续不断地,也可以是相邻两次尝试时间上加上一定的时间延时。有了fcntl()之后则可以使用F_SETTLKW来阻塞直到锁可用为止。

    • 使用open()uunlink()获取和释放锁涉及到的文件系统的操作,这比记录锁要慢得多,

    • 如果一个进程意外的终止并且没有删除锁文件,那么锁就不会被释放。处理这个问题存在特别的技术,包括检查文件的上次修改时间和让锁的持有者将进程ID写入文件,这样就能够检查进程是否存在,但这些计数中没有一项技术是安全可靠的,与之相反的是,在一个进程终止时记录锁的释放操作是原子的。

    • 如果放置多把锁,那么就无法检车出死锁,如果发生了死锁,那么造成死锁的进程就会永远的保持阻塞。

    • 第二版的NFS不支持O_EXCL语义。Linux 2.4NFS客户端也没有正确地实现O_EXCL,即使是第三版的NFS以及以后版本的也没能完成这个任务。

    link(file, lockfile)加上unink()lockfile

    link()系统调用,在新链接已经存在时,会失败的事实可用作一种加锁机制,而解锁功能则还是使用unlink()来完成。常规的做法是让需要获取锁的进程创建一个临时的文件名,一般来将需要包含进程ID。要获取锁则需要将这个临时文件链接到某个约定的标准路径上。如果link()调用成功,那么就获取了锁,如果调用失败EEXIST,那么就是另一个进程持有了锁,因此必须要在稍后的某个时刻重新尝试获取该锁。这项技术与上面介绍的open(file, O_CREAT|O_EXCL, 0)技术存在相同的局限。

    open(file, O_CREAT|O_TRUNC|O_WRONLY, 0)

    当指定O_TRUNC并且写权限被拒绝时在一个既有文件上调用open()会失败的事实,可作为一项几所技术的基础,要获取一把锁可以使用下面的代码,来创建新文件。

    fd=open(file, O_CREAT|O_TRUNC|O_WRONLY, (mode_t)0);

    close(fd);

    如果open()调用成功,那么就获取了锁,如果因EACCES而失败(即文件存在但是没没有人拥有权限),那么其他进程持有了锁,还需要在后面某个时刻尝试重新获取锁。这项计数与前面介绍的技术存在相同的局限,还需要注意的是不能具备超级用户特权的程序使用这项技术,因为open()总是会成功,不管文件上设置的权限是什么。

    总结

    文件加锁使得进程能偶同步对一个文件的访问,Linux提供了两种文件加锁的系统调用

    1. BSD衍生出来的flock()
    2. system V衍生出来的fcntl()

    尽管这两组系统调用在大多数UNIX实现上都是可用的,但只有fcntl()加锁是在SUSv3中进行了标准化。


    flock()系统调用对整个文件加锁,可放置的锁有两种:一种是共享锁,这种锁与其他进程持有的共享锁是兼容的;另一种互斥锁,这种锁能偶阻止其他进程放置这两种锁。


    fcntl()系统调用将一个文件的任意区域上放置一把锁(“记录锁”),这个区域可以是单个字节也可以是整个文件。可放置的锁有两种:读锁和写锁,他们之间的兼容性语义与flock()放置的共享锁和互斥锁之间的兼容语义类似。如果一个阻塞式(F_SETLKW)锁请求将会导致死锁,那么内核将让其中一个受影响的进程的fcntl()失败(返回EDADLK错误)。


    除非系统中的flock()是使用fcntl()实现的,否则使用flock()fcntl()放置的锁之间是相互不可见的,通过flcok()fcntl()放置的锁在fork()中的继承语义和在文件描述符被关闭时的释放语义是不同的。

    Linux特有的/proc/locks文件给出了系统中所有进程当期持有的文件锁。

    展开全文
  • 使用fcntl在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。其中...

    Python的多线程在io方面比单线程还是有优势,但是在多线程开发时,少不了对文件的读写操作。在管理多个线程对同一文件的读写操作时,就少不了文件锁了。

    使用fcntl

    在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。

    对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。

    其中,参数 fd 表示文件描述符;参数 operation 指定要进行的锁操作,该参数的取值有如下几种:

    LOCK_SH:表示要创建一个共享锁,在任意时间内,一个文件的共享锁可以被多个进程拥有

    LOCK_EX:表示创建一个排他锁,在任意时间内,一个文件的排他锁只能被一个进程拥有

    LOCK_UN:表示删除该进程创建的锁

    LOCK_MAND:它主要是用于共享模式强制锁,它可以与 LOCK_READ 或者 LOCK_WRITE联合起来使用,从而表示是否允许并发的读操作或者并发的写操作

    demo

    import fcntl

    import threading

    import time

    def writetoTxt(txtFile):

    id = threading.currentThread().getName()

    with open(txtFile, 'a') as f:

    fcntl.flock(f.fileno(), fcntl.LOCK_EX) #加锁

    print "{0} acquire lock".format(id)

    f.write("write from {0} \r\n".format(id))

    time.sleep(3)

    # 在with块外,文件关闭,自动解锁

    print "{0} exit".format(id)

    for i in range(5):

    myThread = threading.Thread(target=writetoTxt, args=("test.txt",))

    myThread.start()

    代码运行期间,控制台将依次打印哪个线程获得了锁,在对文件进行读写。

    Thread-1 acquire lock

    Thread-1 exit

    Thread-2 acquire lock

    Thread-2 exit

    Thread-3 acquire lock

    Thread-3 exit

    Thread-5 acquire lock

    Thread-5 exit

    Thread-4 acquire lock

    Thread-4 exit

    小结

    通过调用

    fcntl.flock(f.fileno(), fcntl.LOCK_EX)

    对文件加锁,如果有其他线程尝试对test文件加锁,会被阻塞。

    当线程执行完毕的时候,锁会自动释放。或者也可以采取主动的方式解锁:调用

    fcntl.flock(f.fileno(),fcntl.LOCK_UN)

    函数, 对文件test解锁

    使用线程锁

    当多个线程共享一个数据的时候,必须要进行同步的控制,不然会出现不可预期的结果,即 “线程不安全”

    线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。

    互斥锁为资源引入一个状态:锁定/非锁定。

    某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;

    直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。

    互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

    threading模块中定义了Lock类,可以方便的处理锁定:

    #创建锁

    mutex = threading.Lock()

    #锁定

    mutex.acquire([timeout])

    #解锁

    mutex.release()

    Demo

    使用互斥锁实现上面的例子的代码如下:

    import threading

    import time

    def writetoTxt(txtFile):

    id = threading.currentThread().getName()

    mutex.acquire(10)

    with open(txtFile, 'a') as f:

    print "Thread {0} acquire lock".format(id)

    f.write("write from thread {0} \r\n".format(id))

    time.sleep(3)

    mutex.release()

    print "Thread {0} exit".format(id)

    mutex = threading.Lock()

    for i in range(5):

    myThread = threading.Thread(target=writetoTxt, args=("test.txt",))

    myThread.start()

    (上述代码本质上是一个顺序执行的单线程)

    结果:

    Thread Thread-1 acquire lock

    Thread Thread-1 exit

    Thread Thread-2 acquire lock

    Thread Thread-2 exit

    Thread Thread-3 acquire lock

    Thread Thread-3 exit

    Thread Thread-4 acquire lock

    Thread Thread-4 exit

    Thread Thread-5 acquire lock

    Thread Thread-5 exit

    小结

    当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”。

    直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。

    以上这篇对Python多线程读写文件加锁的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

    本文标题: 对Python多线程读写文件加锁的实例详解

    本文地址: http://www.cppcns.com/jiaoben/python/249836.html

    展开全文
  • 使用fcntl在linux下,python的标准库有现成的文件锁,来自于fcntl模块。这个模块提供了unix系统fcntl()和ioctl()的接口。对于文件锁的操作,主要需要使用 fcntl.flock(fd, operation)这个函数。其中...
  • linux文件加锁与解锁

    2020-07-09 17:25:20
    废话少说,贴两个函数,加入到你的项目中,能用。 #include <fcntl.h> intg_file_lock_wait(int fd, int start, int len) { struct flock lock; lock.l_type = F_WRLCK;... if (fcntl(fd, F_SET...
  • LINUX多线程读写同一个文件 加锁

    千次阅读 2016-07-26 17:10:18
    当有多个工作线程要同时对一个文件进行写操作时,如果不对该文件进行加锁就可能会因误操作而引起一系列的问题。  解决这个问题有多种方法。我们这里考虑使用文件锁来对文件进行保护,因为这个方法简单易行。具体...
  • Linux下C/C++给文件加锁

    千次阅读 2019-12-21 23:14:16
    本文主要讲述Linux下如何在C/C++程序中给文件加锁,防止多个进程并发读写同一个文件导致文件内容不一致,使用fcntl()函数,这是一个POSIX函数。 一 为何需要文件锁 假设有一个菜谱文件,其内容是今天需要买的菜,...
  • linux 定时任务 加锁

    千次阅读 2015-06-04 16:37:34
    /3 * * * flock -xn /home/work/yuna/oem_apk_new.lock -c ‘sh /home/work/fupeng/oem_apk_new.sh >/dev/null 2>&1’ >/dev/null 2>&1
  • SVN文件加锁

    2018-04-23 18:55:00
    原文:SVN与TortoiseSVN实战:文件加锁详解 加锁与解锁的操作对于项目中的二进制文件,如图片、声音、动态库等不可合并文件是非常有用的,可以让这些文件防止产生恼人的冲突,但TortoiseSVN中的Get lock的其实并不...
  • Linux 多进程读写文件 文件锁

    千次阅读 2015-07-07 14:30:33
    目前遇到一个问题:多个进程对同一个文件进行写操作,如何避免冲突。研究了一下,做个小结。   对于多进程写文件,主要有以下两种处理方式: ...1.类似于Linux日志文件服务 ...对当前读写文件进行加锁处理,简单说
  • Python 给文件加锁–fcntl 模块 1. 前言 import fcntl 打开一个文件 # 当前目录下test文件要先存在,如果不存在会报错。或者以写的方式打开 f = open('./test') # 对该文件加锁: fcntl.flock(f,fcntl.LOCK_...
  • 多进程如何不加锁读写文件队列

    千次阅读 2013-08-18 16:02:59
    注:以a+方式open一个文件的时候,write...write一个文件内核是加锁的,会保证原子执行。   ssize_t write(int fd, const void *buf, size_t count); 返回值代表写了多少字节,ret 一次write调用相当于原子
  • Linux读写

    2021-08-12 20:02:16
    考虑这样一种场景,多个线程对一个文件进行读写操作,线程操作前先加锁,通常对文件的只读操作不会改变文件的状态,因此可以允许多个线程同时读取文件。如果使用互斥锁是做不到这一点的,这时候读写锁就上场了。读写...
  • 多线程并发思考--文件加锁 在最近的工作中,经常要用到线程,就对线程相关知识稍微看了看,知道并发线程经常引起共享资源冲突,java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持. 可是在工作中,我...
  • 使用系统调用fcntl()来对文件加锁

    千次阅读 2014-09-27 15:12:57
    linux通常采用的方法是文件上锁,来避免共享资源的产生竞争状态。  文件锁包括建议性锁和强制性的锁。建议性的,顾名思义,相对温柔一些,在对文件进行锁操作时,会检测是否已经有锁存在,并且尊重已有的锁。在...
  • fcntl模块: flock() : flock(f, operation) operation : 包括: fcntl.LOCK_UN 解锁 fcntl.LOCK_EX 排他锁 fcntl.LOCK_SH 共享锁 fcntl.LOCK_NB 非阻塞锁 ...LOCK_EX 排他锁:除加锁进程外其他进程没...
  • linux 读写

    2011-01-09 18:06:27
    特性: 读写锁也叫共享——排他锁,因为有3种状态, 所以可以有更高的并行性。...• 当读写锁是写加锁状态时, 在这个锁被解锁之前, 所有试图对这个锁加锁的线程都会被阻塞。 • 当读写锁在读加锁状态时, 所有...
  • Linux文件系统之文件读写

    千次阅读 2013-11-10 19:16:09
    文件读写文件系统中最核心也是最复杂的一部份,它牵涉到了很多的概念.之前分析文件系统其它操作的时候,遇到与文件系统相关的读写部份都忽略过去了.在这一节里,来讨论一下文件读写是怎样实现的. 二:I/O请求的...
  • 文件锁的类型  1、读锁:共享锁,如果A进程对文件
  • Linux 中的mmap映射(读写文件数据的另一种方式) mmap功能 Linux除了通过对read,write函数的调用实现数据的读写,还提供了一种方式,对文件数据进行读写,即利用mmap函数。 例如:用户想要从磁盘上读取8192个字节...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,028
精华内容 8,011
关键字:

linux读写文件加锁

linux 订阅