python给函数加锁 python加锁的方法

下面这段python的多线程代码为什么运行不起来,说是函数没有加锁的属性

下面的代码可以,因为你那个lock是变量又是函数,会冲突的,另外,你这个实验其实测试不出来lock属性,因为你调用实际上是顺序的

在宁安等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站制作、成都网站建设 网站设计制作按需规划网站,公司网站建设,企业网站建设,品牌网站设计,全网营销推广,外贸网站制作,宁安网站建设费用合理。

import string,socket,time,os,sys,threading

num=0

class xThread():

def __init__(self):

self._lock=threading.Lock()

def lock(self):

self._lock.acquire()

def unlock(self):

self._lock.release()

def p2(a):

global num

thread.lock()

num+=1

print(a+str(num))

time.sleep(0.1)

thread.unlock()

def p1(a):

for i in range(3):

info='this %s thread'%(i)

p2(info)

def main():

for i in range(3):

p1(i)

if __name__ == '__main__':

thread=xThread()

main()

python多线程的几种方法

Python进阶(二十六)-多线程实现同步的四种方式

临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区。

锁机制

threading的Lock类,用该类的acquire函数进行加锁,用realease函数进行解锁

import threadingimport timeclass Num:

def __init__(self):

self.num = 0

self.lock = threading.Lock() def add(self):

self.lock.acquire()#加锁,锁住相应的资源

self.num += 1

num = self.num

self.lock.release()#解锁,离开该资源

return num

n = Num()class jdThread(threading.Thread):

def __init__(self,item):

threading.Thread.__init__(self)

self.item = item def run(self):

time.sleep(2)

value = n.add()#将num加1,并输出原来的数据和+1之后的数据

print(self.item,value)for item in range(5):

t = jdThread(item)

t.start()

t.join()#使线程一个一个执行12345678910111213141516171819202122232425262728

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

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

信号量

信号量也提供acquire方法和release方法,每当调用acquire方法的时候,如果内部计数器大于0,则将其减1,如果内部计数器等于0,则会阻塞该线程,知道有线程调用了release方法将内部计数器更新到大于1位置。

import threadingimport timeclass Num:

def __init__(self):

self.num = 0

self.sem = threading.Semaphore(value = 3) #允许最多三个线程同时访问资源

def add(self):

self.sem.acquire()#内部计数器减1

self.num += 1

num = self.num

self.sem.release()#内部计数器加1

return num

n = Num()class jdThread(threading.Thread):

def __init__(self,item):

threading.Thread.__init__(self)

self.item = item def run(self):

time.sleep(2)

value = n.add()

print(self.item,value)for item in range(100):

python log 文件锁判断是否有锁

Python的文件锁目前使用的是fcntl这个库,它实际上为 Unix上的ioctl,flock和fcntl 函数提供了一个接口。

1.fcntl库的简单使用

[python] view plain copy

import fcntl

import os, time

FILE = "counter.txt"

if not os.path.exists(FILE):

# create the counter file if it doesn't exist

file = open(FILE, "w")

file.write("0")

file.close()

for i in range(20):

file = open(FILE, "r+") #由于flock生成的是劝告锁,不能阻止进程对文件的操作,所以这里可以正常打开文件

fcntl.flock(file.fileno(), fcntl.LOCK_EX) #为了避免同时操作文件,需要程序自己来检查该文件是否已经被加锁。这里如果检查到加锁了,进程会被阻塞

print 'acquire lock'

counter = int(file.readline()) + 1

file.seek(0)

file.write(str(counter))

print os.getpid(), "=", counter

time.sleep(10)

file.close() # unlocks the file

print 'release lock'

time.sleep(3)

分别启动2个进程来同时运行这个脚本,我们可以很明显的看到2者互相之间交替阻塞。同一时刻只有一个进程能够对counter.txt文件进行操作。

2.对fcntl.flock()函数的说明:

linux的flock() 的函数原型如下所示:

int flock(int fd, int operation);

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

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

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

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

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

通常情况下,如果加锁请求不能被立即满足,那么系统调用 flock()会阻塞当前进程。比如,进程想要请求一个排他锁,但此时,已经由其他进程获取了这个锁,那么该进程将会被阻塞。如果想要在没有获得这个排他锁的情况下不阻塞该进程,可以将LOCK_NB 和 LOCK_SH 或者 LOCK_EX 联合使用,那么系统就不会阻塞该进程。flock()所加的锁会对整个文件起作用。

注意:

1. 对于文件的 close() 操作会使文件锁失效;

2. 同理,进程结束后文件锁失效;

3. flock() 的 LOCK_EX是“劝告锁”,系统内核不会强制检查锁的状态,需要在代码中进行文件操作的地方显式检查才能生效。

Python多线程总结

在实际处理数据时,因系统内存有限,我们不可能一次把所有数据都导出进行操作,所以需要批量导出依次操作。为了加快运行,我们会采用多线程的方法进行数据处理, 以下为我总结的多线程批量处理数据的模板:

主要分为三大部分:

共分4部分对多线程的内容进行总结。

先为大家介绍线程的相关概念:

在飞车程序中,如果没有多线程,我们就不能一边听歌一边玩飞车,听歌与玩 游戏 不能并行;在使用多线程后,我们就可以在玩 游戏 的同时听背景音乐。在这个例子中启动飞车程序就是一个进程,玩 游戏 和听音乐是两个线程。

Python 提供了 threading 模块来实现多线程:

因为新建线程系统需要分配资源、终止线程系统需要回收资源,所以如果可以重用线程,则可以减去新建/终止的开销以提升性能。同时,使用线程池的语法比自己新建线程执行线程更加简洁。

Python 为我们提供了 ThreadPoolExecutor 来实现线程池,此线程池默认子线程守护。它的适应场景为突发性大量请求或需要大量线程完成任务,但实际任务处理时间较短。

其中 max_workers 为线程池中的线程个数,常用的遍历方法有 map 和 submit+as_completed 。根据业务场景的不同,若我们需要输出结果按遍历顺序返回,我们就用 map 方法,若想谁先完成就返回谁,我们就用 submit+as_complete 方法。

我们把一个时间段内只允许一个线程使用的资源称为临界资源,对临界资源的访问,必须互斥的进行。互斥,也称间接制约关系。线程互斥指当一个线程访问某临界资源时,另一个想要访问该临界资源的线程必须等待。当前访问临界资源的线程访问结束,释放该资源之后,另一个线程才能去访问临界资源。锁的功能就是实现线程互斥。

我把线程互斥比作厕所包间上大号的过程,因为包间里只有一个坑,所以只允许一个人进行大号。当第一个人要上厕所时,会将门上上锁,这时如果第二个人也想大号,那就必须等第一个人上完,将锁解开后才能进行,在这期间第二个人就只能在门外等着。这个过程与代码中使用锁的原理如出一辙,这里的坑就是临界资源。 Python 的 threading 模块引入了锁。 threading 模块提供了 Lock 类,它有如下方法加锁和释放锁:

我们会发现这个程序只会打印“第一道锁”,而且程序既没有终止,也没有继续运行。这是因为 Lock 锁在同一线程内第一次加锁之后还没有释放时,就进行了第二次 acquire 请求,导致无法执行 release ,所以锁永远无法释放,这就是死锁。如果我们使用 RLock 就能正常运行,不会发生死锁的状态。

在主线程中定义 Lock 锁,然后上锁,再创建一个子 线程t 运行 main 函数释放锁,结果正常输出,说明主线程上的锁,可由子线程解锁。

如果把上面的锁改为 RLock 则报错。在实际中设计程序时,我们会将每个功能分别封装成一个函数,每个函数中都可能会有临界区域,所以就需要用到 RLock 。

一句话总结就是 Lock 不能套娃, RLock 可以套娃; Lock 可以由其他线程中的锁进行操作, RLock 只能由本线程进行操作。


文章标题:python给函数加锁 python加锁的方法
文章分享:http://pwwzsj.com/article/hijeij.html