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

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多线程读写文件加锁的实例详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 详解python多线程、锁、event事件机制的简单使用

    线程和进程 1.线程共享创建它的进程的地址空间,进程有自己的地址空间 2.线程可以访问进程所有的数据,线程可以相互访问 3.线程之间的数据是独立的 4.子进程复制线程的数据 5.子进程启动后是独立的 ,父进程只能杀掉子进程,而不能进行数据交换 6.修改线程中的数据,都是会影响其他的线程,而对于进程的更改,不会影响子进程 threading.Thread Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run

  • Python多线程编程(七):使用Condition实现复杂同步

    目前我们已经会使用Lock去对公共资源进行互斥访问了,也探讨了同一线程可以使用RLock去重入锁,但是尽管如此我们只不过才处理了一些程序中简单的同步现象,我们甚至还不能很合理的去解决使用Lock锁带来的死锁问题.所以我们得学会使用更深层的解决同步问题. Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法. 使用Condition的主要方式为:线程

  • Python中使用Queue和Condition进行线程同步的方法

    Queue模块保持线程同步 利用Queue对象先进先出的特性,将每个生产者的数据一次存入队列,而每个消费者将依次从队列中取出数据 import threading # 导入threading模块 import Queue # 导入Queue模块 class Producer(threading.Thread):# 定义生产者类 def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) def

  • python多线程threading.Lock锁用法实例

    本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 复制代码 代码如下: mutex = threading.Lock() #锁的使用 #创建锁 mutex = threading.Lock() #锁定 mutex.acquire([timeout]) #释放 mutex.release() 锁定方法acquire可以有一个超时时间的可选参数timeout.如果设定了timeout,则在超时后通过返回值

  • python多线程高级锁condition简单用法示例

    本文实例讲述了python多线程高级锁condition简单用法.分享给大家供大家参考,具体如下: 多线程编程中如果使用Condition对象代替lock, 能够实现在某个事件触发后才处理数据, condition中含有的方法: - wait:线程挂起,收到notify通知后继续运行 - notify:通知其他线程, 解除其它线程的wai状态 - notifyAll(): 通知所有线程 - acquire和release: 获得锁和解除锁, 与lock类似, - enter和exit使得对象支持

  • Python实现的多线程同步与互斥锁功能示例

    本文实例讲述了Python实现的多线程同步与互斥锁功能.分享给大家供大家参考,具体如下: #! /usr/bin/env python #coding=utf-8 import threading import time ''' #1.不加锁 num = 0 class MyThread(threading.Thread): def run(self): global num time.sleep(1) #一定要sleep!!! num = num + 1 msg = self.name + '

  • Python中多线程及程序锁浅析

    Python中多线程使用到Threading模块.Threading模块中用到的主要的类是Thread,我们先来写一个简单的多线程代码: 复制代码 代码如下: # coding : uft-8 __author__ = 'Phtih0n' import threading class MyThread(threading.Thread):     def __init__(self):         threading.Thread.__init__(self) def run(self):

  • Python多线程中阻塞(join)与锁(Lock)使用误区解析

    关于阻塞主线程 join的错误用法 Thread.join() 作用为阻塞主线程,即在子线程未返回的时候,主线程等待其返回然后再继续执行. join不能与start在循环里连用 以下为错误代码,代码创建了5个线程,然后用一个循环激活线程,激活之后令其阻塞主线程. threads = [Thread() for i in range(5)] for thread in threads: thread.start() thread.join() 执行过程: 1. 第一次循环中,主线程通过start函

  • Python多线程编程(六):可重入锁RLock

    考虑这种情况:如果一个线程遇到锁嵌套的情况该怎么办,这个嵌套是指当我一个线程在获取临界资源时,又需要再次获取. 根据这种情况,代码如下: 复制代码 代码如下: ''' Created on 2012-9-8   @author: walfred @module: thread.ThreadTest6 '''    import threading  import time    counter = 0  mutex = threading.Lock()    class MyThread(thr

  • python使用threading.Condition交替打印两个字符

    Python中使用threading.Condition交替打印两个字符的程序. 这个程序涉及到两个线程的的协调问题,两个线程为了能够相互协调运行,必须持有一个共同的状态,通过这个状态来维护两个线程的执行,通过使用threading.Condition对象就能够完成两个线程之间的这种协调工作. threading.Condition默认情况下会通过持有一个ReentrantLock来协调线程之间的工作,所谓可重入锁,是只一个可以由一个线程递归获取的锁,此锁对象会维护当前锁的所有者(线程)和当前所

  • Python多线程编程(四):使用Lock互斥锁

    前面已经演示了Python:使用threading模块实现多线程编程二两种方式起线程和Python:使用threading模块实现多线程编程三threading.Thread类的重要函数,这两篇文章的示例都是演示了互不相干的独立线程,现在我们考虑这样一个问题:假设各个线程需要访问同一公共资源,我们的代码该怎么写? 复制代码 代码如下: ''' Created on 2012-9-8   @author: walfred @module: thread.ThreadTest3 '''  impor

  • Python多线程编程(五):死锁的形成

    前一篇文章Python:使用threading模块实现多线程编程四[使用Lock互斥锁]我们已经开始涉及到如何使用互斥锁来保护我们的公共资源了,现在考虑下面的情况– 如果有多个公共资源,在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,这会引起什么问题? 死锁概念 所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程.

随机推荐