线程锁的运用

1. 为什么需要线程锁?

多个线程对同一个数据进行修改时, 可能会出现不可预料的情况.

2. 如何实现线程锁?

# 1. 实例化一个锁对象;
#     lock = threading.Lock()
# 2. 操作变量之前进行加锁
#     lock.acquire()
# 3. 操作变量之后进行解锁
#     lock.release()

线程锁在程序中运用

import threading


#  以银行存钱和取钱举例
def add(lock):
    global money  # 生命money为全局变量
    for i in range(1000):
        # 2. 操作变量之前进行加锁
        lock.acquire()
        money += 1
        # 3. 操作变量之后进行解锁
        lock.release()

def reduce(lock):
    global money
    for i in range(1000):
        # 2. 操作变量之前进行加锁
        lock.acquire()
        money -= 1
        # 3. 操作变量之后进行解锁
        lock.release()


if __name__ == '__main__':
    money=0
    # 1. 实例化一个锁对象;
    lock = threading.Lock()
    t1 = threading.Thread(target=add, args=(lock,))
    t2 = threading.Thread(target=reduce, args=(lock,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("当前金额:", money)


# 当使用继承来实现多线程
import threading
class AddThread(threading.Thread):
    def __init__(self, lock):
        super(AddThread, self).__init__()
        self.lock = lock
    def run(self):
        for i in range(1000000):
            # 2. 操作变量之前进行加锁
            self.lock.acquire()
            global  money
            money += 1  # money;  money+1; money=money+1;
            # 3. 操作变量之后进行解锁
            self.lock.release()

class ReduceThread(threading.Thread):
    def __init__(self, lock):
        super(ReduceThread, self).__init__()
        self.lock = lock
    def run(self):
        global money
        for i in range(1000000):
            # 2. 操作变量之前进行加锁
            lock.acquire()
            money -= 1
            # 3. 操作变量之后进行解锁
            lock.release()
if __name__ == '__main__':
    money = 0
    # 1. 实例化一个锁对象;
    lock = threading.Lock()
    t1 = AddThread(lock)
    t2 = ReduceThread(lock)
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("当前金额:", money)

再比如实现多线程下载,以下是下载器的程序:

# 实现多线程的下载器
import threading
from urllib.request import urlopen

DOWNLOAD_DIR = 'doc'
class DownloadThread(threading.Thread):
    def __init__(self, url):
        super(DownloadThread, self).__init__()
        self.url = url
    def run(self):
        try:
            urlObj = urlopen(self.url)
        except Exception as e:
            print("download %s error\n" % (self.url), e)
            imgContent = None
        else:

            filename = self.url.split("/")[-1]
            # 'wb' === 写的是二进制文件(图片, 视频, 动图, .pdf)
            # 'ab'
            with open("%s/%s" % (DOWNLOAD_DIR, filename), 'ab') as f:
                # 如果文件特别大的时候, 建议分块下载;每次只读取固定大小, 防止占用内存过大.
                while True:
                    imgContentChunk = urlObj.read(1024 * 3)
                    if not imgContentChunk:
                        break
                    f.write(imgContentChunk)
                    # 可以添加下载的程度(百分率);

                print("%s下载成功" % (filename))
url1='https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1566735794&di=37ecfaf0fa4f16f616b86be7b9a7091a&src=http://b-ssl.duitang.com/uploads/item/201808/27/20180827030547_tsblg.jpg'
url2='https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1566745890473&di=364b5eca93978f39c8ae55000323d757&imgtype=0&src=http%3A%2F%2Fpic19.nipic.com%2F20120227%2F3145425_092317138000_2.jpg'
urls = [url1,url2]

for url in urls:
    thread = DownloadThread(url)
    thread.start()
    thread.join()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值