线程,共享资源,锁

线程的概念

进程的概念:运行着的程序
每个进程里面至少有一个线程
线程是操作系统创建的,用力啊控制代码执行的数据结构
线程就像代码的执行许可证

单线程程序。主线程的入口就是代码的开头
主线程顺序往下执行,直到所有的代码都执行完

**

概念对应(银行里面办理业务)

**
一个服务窗口 = CPU的一个核
客户 = 进程(运行着的程序)
调度员 = 操作系统(OS)
服务号 = 线程
调度员分配服务号给客户 = OS分配线程给进程代码
服务窗口给客户办理业务 = CPU核心执行线程代码

调度的概念

    调度员分配窗口给客户
    一个客户不一定占用一个窗口直到它结束
    比如需要很长时间填写表格
    这是可以让下一个客户办理
    先前的客户填好了表格,在继续

操作系统不会让一个线程一直占用CPU的

进程里的多线程

线程库
代码通过系统调用,请求os分配一个新的线程
python里面使用封装好的库,python3只有threading,是标准库里面的
thread
threading
都可以用来创建和管理线程
thread比较底层
threading是thread模块的扩展,提供了很多线程同步功能,使用起来更加方便强大

例子:

print("main thread start.")

import threading
from time import sleep

def thread1_entry():
    print("child thread 1,start")
    sleep(15)
    print("child thread 1,end")

t1 = threading.Thread(target=thread1_entry)    #Thread是一个类Thread()是实例化一个类,传入初始化方法的参数,target传的是这个函数的名字,不是调用。不加括号是函数的对象。
t1.start()     #t1是Thread的实例对象,从这个点开始就启动了一个新的线程
sleep(10)    #主线程要sleep10秒    主线程先结束
print("main thread end.")

#结果

main thread start.
child thread 1,start
main thread end.
child thread 1,end

有些场景是:主线程要等待子线程执行完,比如子线程爬去数据,主线程分析数据、
要等到子线程结束(线程的.join()方法)

import threading
from time import sleep,ctime,time

def thread1_entry(nsec):
    print("child thread 1,start at:",ctime())
    sleep(nsec)
    print("child thread 1,end at:",ctime())


def thread2_entry(nsec):
    print("child thread 2,start at:",ctime())
    sleep(nsec)
    print("child thread 2,end at:",ctime())


print("main thread start.")
#创建线程对象,指定了新线程的入口函数,args是传入入口函数的参数
t1 = threading.Thread(target=thread1_entry,args=(1,))    #Thread是一个类Thread()是实例化一个类,传入初始化方法的参数
t2 = threading.Thread(target=thread2_entry,args=(2,))   #(1,)元组,args=(1,)是入口函数的参数,就是用args传给他,只能传元组,一个元素的时候,一定要加逗号,这里是传入的是时间

#启动新线程
t1.start()   #两个线程的实例化。调用start方法
t2.start()

start = time()    #验证json等待的时间

#主线程等待t1线程结束,
t1.join()
#主线程等待t2线程结束
t2.join()

end = time()        #验证json等待的时间
print(end-start)        #验证json等待的时间

print("main thread end.")

#结果:

# main thread start.
# child thread 1,start at: Sat Nov 10 18:06:26 2018
# child thread 2,start at: Sat Nov 10 18:06:26 2018
# child thread 1,end at: Sat Nov 10 18:06:27 2018
# child thread 2,end at: Sat Nov 10 18:06:28 2018
# 2.0
# main thread end.

多线程使用共享数据

共享对象的概念

从例子说起
高铁上的测试
某个时刻只能一个人使用
进入后往往立刻锁门(表示已经被使用)
看到的人,门口排队等待
用完开锁(表示已经使用完了)
排队的人中下一个去使用(重复这个过程)

有些资源是某个时刻时刻独占使用的
如果不加锁
某人使用厕所
另一个人也进入使用
发生冲突
锁保证了
只有一个人去使用
别人必须等待

 import threading
 from time import sleep,ctime,time

#存储支付宝账号余额
zhifubao = {
    "jcy":100000,
    "liming":5000,
    "wangmin":15000,
    "zhaolei":6500000,
}
#线程1:滴滴打车处理,参数是用户账户和扣款金额
def thread1_didi_pay(account,amount):
    print("* t1:get balance from bank")
    balance = zhifubao[account]    #通过账户把余额取出来,放到一个变量里面

    #下面的sleep(2)表示一些处理过程中需要花上2秒钟
    print("* t1:do something(like discount lookup) for 2 seconds")
    sleep(2)

    print("* t1:deduct")

    zhifubao[account] = balance - amount    #把余额扣掉

#线程2:余额宝处理,参数是用户账户和当前利息

def thread2_yuebao_interest(account, amount):
    print("$ t2:get balance from bank")
    balance = zhifubao[account]

    # 下面的sleep(1)表示一些处理过程中需要花上1秒钟
    print("$ t2:do something2...... for 2 seconds")
    sleep(1)

    print("$ t2: add")

    zhifubao[account] = balance + amount    ##余额每天的收益


t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10))  #创立两个线程对象
t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))

t1.start()
t2.start()

t1.join()
t2.join()
print("finally,jcy balance is %s"%zhifubao["jcy"])

#结果

# * t1:get balance from bank
# * t1:do something(like discount lookup) for 2 seconds
# $ t2:get balance from bank
# $ t2:do something2...... for 2 seconds
# $ t2: add
# * t1:deduct
# finally,jcy balance is 99990

#应该是10万元
#多个线程要访问共享数据的时候,特别是要修改数据的时候。我们可以使用锁对象的机制。同时只有一个线程处理他的时候,就不会有问题

import threading
from time import sleep,ctime,time

#存储支付宝账号余额
zhifubao = {
    "jcy":100000,
    "liming":5000,
    "wangmin":15000,
    "zhaolei":6500000,
}

#调用Lock函数,返回一个锁对象
zhifubao_lock = threading.Lock()

#线程1:滴滴打车处理,参数是用户账户和扣款金额
def thread1_didi_pay(account,amount):
    #在代码访问共享对象之前,加锁
    #当多个线程同时执行lock.acquire()时,
    #只有一个线程能成功的获取锁,然后继续执行代码
    #其他线程就继续等待,直到获得锁为止
    zhifubao_lock.acquire()
    print("* t1:get balance from bank")
    balance = zhifubao[account]    #通过账户把余额取出来,放到一个变量里面

    #下面的sleep(2)表示一些处理过程中需要花上2秒钟
    print("* t1:do something(like discount lookup) for 2 seconds")
    sleep(2)

    print("* t1:deduct")

    zhifubao[account] = balance - amount    #把余额扣掉
    #访问共享对象释放锁
    #访问结束后,一定要调用Lock对象的release方法,进行解锁操作
    #否则其他等待锁的线程将永远等待下去
    zhifubao_lock.release()
#线程2:余额宝处理,参数是用户账户和当前利息

def thread2_yuebao_interest(account, amount):
    zhifubao_lock.acquire()   #代码访问共享对象之前,加锁
    print("$ t2:get balance from bank")
    balance = zhifubao[account]

    # 下面的sleep(1)表示一些处理过程中需要花上1秒钟
    print("$ t2:do something2...... for 2 seconds")
    sleep(1)

    print("$ t2: add")

    zhifubao[account] = balance + amount    ##余额每天的收益
    zhifubao_lock.release()    #访问完共享对象 释放锁

t1 = threading.Thread(target=thread1_didi_pay,args=("jcy",10))  #创立两个线程对象
t2 = threading.Thread(target=thread2_yuebao_interest,args=("jcy",10))

t1.start()
t2.start()

t1.join()
t2.join()
print("finally,jcy balance is %s"%zhifubao["jcy"])

#结果

# * t1:get balance from bank
# * t1:do something(like discount lookup) for 2 seconds
# * t1:deduct
# $ t2:get balance from bank
# $ t2:do something2...... for 2 seconds
# $ t2: add
# finally,jcy balance is 100000    

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37615098/article/details/83933614
今日推荐