python 多线程threading锁机制与异常处理的问题

前言

前几天做了一个爬虫,其作用大体是在网上爬取数据并把数据插入数据库。由于收集数据实在是太慢,于是使用了多线程爬取,因为其中有插入数据的操作,为以防多线程同时向数据库插入数据时抛出异常,于是加了锁机制,或许是因为死锁执行过程中有几次都卡住了,于是思考线程锁机制与抛出异常的处理问题。

实战

加入多线程的代码

try:
    lock.acquire()
    '''
    这里是插入数据库的语句,具体我就不写了
    '''
    lock.release()
except:
      print("插入数据失败...")
      pass

但是这里出现一个问题,我在运行途中有几次都卡住了,但是python也没有执行print语句,在思考其中的逻辑后,自己认为应该是这样,在加锁后数据库插入错误,于是准备抛出异常给python,但是由于锁没有被释放异常并没有被python接受到,所以print语句也不会执行,于是就陷入了死锁。

在思考一番后重新修改了代码

try:
    lock.acquire(timeout=60)
    '''
    这里是插入数据库的语句,具体我就不写了
    '''
    lock.release()
except:
      print("插入数据失败...")
      pass

当锁在60秒后会自动释放,python正确接受异常并且执行成功,此时算是大功告成了!!!

但是,事情并非如此,在思考完代码逻辑后会发现,如果说插入语句确实超过了60秒,而锁自动释放了,但是接下来再次release的话依然会抛出异常,因为此时并没有加锁,释放锁会出现错误,但是此时数据库应是插入成功的,于是修改最终代码。

终极代码

try:
    lock.acquire(timeout=60)
    '''
    这里是插入数据库的语句,具体我就不写了
    '''
    if lock.locked():
        lock.release()
except:
      print("插入数据失败...")
      pass

(分隔线......)

2020.5.4更新

前面我对线程锁的概念其实是有一点误解的,被大佬点通了一下,看了一下官方文档lock.acquire指定timeout是指在指定时间内让线程去获取那把锁,如果没有获取到则返回一个布尔值(具体是什么我又忘记了,我要去补习一下这类知识了)

还有一点很重要,其实向数据库插入数据不需要加锁,完全多此一举,在mysql中,向表中插入数据是原子性操作,不必担心插入异常,但如果在数据库中插入多表则要考虑锁机制了,因为这并不是原子性操作。

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注