Effective Python 读书笔记: 第38条: 在线程中使用Lock来防止数据竞争

# -*- encoding: utf-8 -*-

from threading import Lock
from threading import Thread

'''
第38条: 在线程中使用Lock来防止数据竞争

关键:
1 关于线程安全问题
python解释器在执行两个连续的字节码指令时,其他线程
可能会插入进来。
本质: 非原子操作会被打断可能带来脏数据,导致线程不安全

2 解决多线程不安全问题
解决方法: 采用互斥锁,即threading.Lock类
原理: 同一时刻,只有一个线程可以获得锁

3 总结
GIL锁不能保证多线程安全,对于非原子操作需要加锁。

参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''

class Counter(object):
    def __init__(self):
        self.count = 0

    def increment(self, value):
        self.count += value


def worker(sensorIndex, numbers, counter):
    for value in range(numbers):
        counter.increment(1)


def runThreads(func, numbers, counter):
    threads = []
    for i in range(5):
        thread = Thread(target=func, args=(i, numbers, counter))
        threads.append(thread)
        thread.start()
    for thread in threads:
        thread.join()


def computeWrong():
    numbers = 10 ** 5
    counter = Counter()
    runThreads(worker, numbers, counter)
    result = counter.count
    print "Expected: {value}, actually: {result}".format(
        value=5 * numbers,
        result=result
    )


class LockingCounter(object):
    def __init__(self):
        self.lock = Lock()
        self.count = 0

    def increment(self, value):
        with self.lock:
            self.count += value


def computeCorrect():
    numbers = 10 ** 5
    counter = LockingCounter()
    runThreads(worker, numbers, counter)
    result = counter.count
    print "Expected: {value}, actually: {result}".format(
        value=5 * numbers,
        result=result
    )


def process():
    computeWrong()
    computeCorrect()


if __name__ == "__main__":
    process() 

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/88958478