python 线程锁_python线程学习-线程锁

python 线程同步:锁 可重入锁 信号量 状态量 事件 队列

这篇文章是来讲述python 线程的同步机制详情。我们将学习到锁 可重入锁 信号量 状态量 事件 队列

首先我们先看一个简单的例子,这个例子中使用到了线程模块但没有使用同步机制

这个类FetchUrls是一个基于线程的类,它将操作一个urls列表,然后写入一个文件

class FetchUrls(threading.Thread):

"""

Thread checking URLs.

"""

def __init__(self, urls, output):

"""

Constructor.

@param urls list of urls to check

@param output file to write urls output

"""

threading.Thread.__init__(self)

self.urls = urls

self.output = output

def run(self):

"""

Thread run method. Check URLs one by one.

"""

while self.urls:

url = self.urls.pop()

req = urllib2.Request(url)

try:

d = urllib2.urlopen(req)

except urllib2.URLError, e:

print 'URL %s failed: %s' % (url, e.reason)

self.output.write(d.read())

print 'write done by %s' % self.name

print 'URL %s fetched by %s' % (url, self.name)

通过这个主函数来调用

def main():

# list 1 of urls to fetch

urls1 = ['http://www.google.com', 'http://www.facebook.com']

# list 2 of urls to fetch

urls2 = ['http://www.yahoo.com', 'http://www.youtube.com']

f = open('output.txt', 'w+')

t1 = FetchUrls(urls1, f)

t2 = FetchUrls(urls2, f)

t1.start()

t2.start()

t1.join()

t2.join()

f.close()

if __name__ == '__main__':

main()

现在的情况是所有的线程都将同时写入文件,结果非常混乱,我们需要找到一种方式-使用一个线程来

写入文件,这样就需要用到像锁这样的同步机制

lock 锁

锁具有2个状态:locked 和 unlocked 。有2个方法要被用于操作这两个状态:acquire() 和

release(),它们具有以下规则:

如果状态是非锁定的,调用acquire()将状态改变为锁定

如果状态是锁定的,调用acquire()将阻塞直到其他线程调用release()

如果状态是非锁定的,调用release() 将会触发RuntimeError 异常

如果状态是锁定的,调用release()将会状态改变为非锁定的

为了解2个线程同时写入同一个文件的问题,我们将在FetchUrls 构造函数中加入锁lock,用它来

保护文件写入行为。

class FetchUrls(threading.Thread):

...

def __init__(self, urls, output, lock):

...

self.lock = lock

def run(self):

...

while self.urls:

...

self.lock.acquire()

print 'lock acquired by %s' % self.name

self.output.write(d.read())

print 'write done by %s' % self.name

print 'lock released by %s' % self.name

self.lock.release()

...

def main():

...

lock = threading.Lock()

...

t1 = FetchUrls(urls1, f, lock)

t2 = FetchUrls(urls2, f, lock)

...

我们来看一下python的内部原理,我使用的是 python2.6.6 linux

lock() 方法相当于 thread.allocate_lock,你可以在Lib/threading.py中找到

Lock = _allocate_lock

_allocate_lock = thread.allocate_lock

略过内部c语言实现

你也可以使用with关键字,这样Lock对象就可以当作内容控制,当程序执行到with语块时,acquire()

方法将会被调用,当with语块执行完成时 release()方法将会被调用,下面是使用with语法来实现

FetchUrls类

class FetchUrls(threading.Thread):

...

def run(self):

...

while self.urls:

...

with self.lock:

print 'lock acquired by %s' % self.name

self.output.write(d.read())

print 'write done by %s' % self.name

print 'lock released by %s' % self.name

...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值