#并发:是指系统具有处理多个任务(动作)的能力
#并行:是指系统具有同时处理多个任务(动作)的能力
#同步:当进程执行到一个IO(等待外部数据,或者下载上传等)的时候 -----------等待:这个就是同步
#异步:当进程执行到一个IO(等待外部数据,或者下载上传等)的时候 -----------不等待而去执行其他操作,到数据接收成功再来执行:这个就是异步
#同步锁
import threading
import time
def foo():
global num #在每个线程中都能获取这个全局变量
num -= 1
def foo1():
global num #在每个线程中都能获取这个全局变量
lock.acquire()#加锁
temp = num
time.sleep(0.1)
num = temp-1
lock.release()#释放锁
num = 10
lock = threading.Lock()#创建一个同步锁对象
l = []
for i in range(10):
t = threading.Thread(target=foo1)
t.start()
l.append(t)
for t in l:
t.join()
print(num)#当用foo创建了10个线程,num的最终结果得到的是0,用foo1创建了10个线程,num的最终结果得到的是9,或者8等等为什么呢
#这个就是同步锁了,我们知道同一进程下所有线程共享进程所具有的资源,在foo函数中得到的结果是0,是因为内存运算速度非常快,
# 所以每个线程运行时函数都已经拿到最新的num的值了;而在foo1中,我们让系统认为的阻塞了一下,这时线程在运行时,就会导致很多线
# 程拿到的都是初始的那个num,这样就会导致运算出来的结果是不对的,那我们怎么解决这个问题呢????
# 我们可以每个线程之后都join(),但是这样的话整段代码都失去了并发的意义
#加同步锁
#加上同步锁之后我们就解决的这个问题,加上同步锁之后,我们在加锁的代码部分同一时间只能运行一个线程,
# 这样我们的到的数据就是每次运行结束之后的最新数据了,但是有一个问题就是这样的话,在加锁的部位我们的并发就失去了意义,不过比join要好一点
#线程死锁和递归锁
import threading,time
class myThread(threading.Thread):
def doA(self):
#lockA.acquire()
lock.acquire()
print(self.name,'gotlockA',time.ctime())
time.sleep(3)
lock.acquire()
#lockB.acquire()
print(self.name, 'gotlockB', time.ctime())
lock.release()
lock.release()
# lockB.release()
# lockA.release()
def doB(self):
lock.acquire()
#lockB.acquire()
print(self.name, 'gotlockB', time.ctime())
time.sleep(3)
lock.acquire()
#lockA.acquire()
print(self.name, 'gotlockA', time.ctime())
# lockA.release()
# lockB.release()
lock.release()
lock.release()
def run(self):
self.doA()
self.doB()
if __name__ == '__main__':
# lockA = threading.Lock()
# lockB = threading.Lock()
lock = threading.RLock()#这个就是递归锁
l = []
for i in range(5):
l.append(myThread())
for t in l:
t.start()
for t in l:
t.join()
print('ending----------')
# 打印结果
# Thread-1 gotlockA Fri Dec 4 11:30:55 2020
# Thread-1 gotlockB Fri Dec 4 11:30:58 2020
# Thread-1 gotlockB Fri Dec 4 11:30:58 2020
# Thread-2 gotlockA Fri Dec 4 11:30:58 2020
#我们发现运行之后,系统打印这些结果之后就不在打印了,并没有走到最后一步打印出ending----------为什么呢。。。。。
#这是因为造成了死锁,怎么造成的,且听我一一道来
# 线程1走完doA之后,开始走doB了,此时线程2开始走doA了,线程1这时获得了B锁,接着往下走准备获得A锁,而此时线程2已经获得了A锁,
# 然后线程1等着A锁释来取得A锁,而线程2还没有到释放A锁的时候,此时线程2该获得B锁了,但是线程1拿着B锁,也没有到释放的时候,
# 这时两个线程都释放不了各自的锁,而且都拿着对方需要的锁,就这死锁就出现了,程序阻塞。怎么解决??
#加递归锁
#把下面这两个锁改为lock= threading.RLock()
# lockA = threading.Lock()
# lockB = threading.Lock()
#其实递归锁的原理核心是一个count计数,就是当这个锁大于0时说明有线程在用,而其他线程就用不了,当这个锁计数是0时,其他线程才能用
'''
# 1 一个程序至少有一个进程,一个进程至少有一个线程.(进程可以理解成线程的容器)
# 2 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
# 3 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和
# 程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
# 4 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调 度的一个独立单位.
# 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程
# 自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈)但是
# 它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
# 一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行
'''
import time
import threading
class Account:
def __init__(self, _id, balance):
self.id = _id
self.balance = balance
self.lock = threading.RLock()
def withdraw(self, amount):
with self.lock:
self.balance -= amount
def deposit(self, amount):
with self.lock:
self.balance += amount
def drawcash(self, amount):#lock.acquire中嵌套lock.acquire的场景
with self.lock:#这个加锁去锁的方式和with open(file,'r')差不多的用法,运行完自己释放锁
interest=0.05
count=amount+amount*interest
self.withdraw(count)
def transfer(_from, to, amount):
#锁不可以加在这里 因为其他的其它线程执行的其它方法在不加锁的情况下数据同样是不安全的
_from.withdraw(amount)
to.deposit(amount)
alex = Account('alex',1000)
yuan = Account('yuan',1000)
t1=threading.Thread(target = transfer, args = (alex,yuan, 100))
t1.start()
t2=threading.Thread(target = transfer, args = (yuan,alex, 200))
t2.start()
t1.join()
t2.join()
print('>>>',alex.balance)
print('>>>',yuan.balance)
'''
def add():
sum=0
for i in range(10000):
sum+=i
print("sum",sum)
def mul():
sum2=1
for i in range(1,100000):
sum2*=i
print("sum2",sum2)
import threading,time
start=time.time()
t1=threading.Thread(target=add)
t2=threading.Thread(target=mul)
l=[]
l.append(t1)
l.append(t2)
for t in l:
t.start()
for t in l:
t.join()
# add()
# mul()
print("cost time %s"%(time.time()-start))
#add() mul()串行执行时时间是cost time 28.294472455978394
#使用线程并发运行时的时间是cost time 29.023944854736328
#为什么并发的时间比串行的时间长
#python 在跑并发时,都是一个核跑的
#问题:多核没利用上?
#GIL 全局解释锁
#无论你启用多少个线程,你有多少个CPU,Python在执行的时候都会淡定的在同一时刻只允许一个线程运行
#因为有GIL,所以。同一时刻,只有一个线程被执行,而在并行时线程在快速的切换争夺CPU,所以在串行的时候比并行的快
#解决方法
#可以把线程放到进程里面,这样就可以解决这个问题了
#多进程+协程
#第一个例子为什么会实现并发时间少
#原因是第一个例子是IO了,所以会并发时间少,sleep()等同于IO操作
#任务:IO密集型,计算密集型
#IO密集型使用并发会大量缩减时间,计算密集型使用并发会比串行执行时间会更长
#对于IO密集型的任务:Python的多线程是有意义的
#对于计算密集型的任务,Python的多线程就不推荐了,Python就不适用了,可以使用进程+协程
#并发:是指系统具有处理多个任务(动作)的能力#并行:是指系统具有同时处理多个任务(动作)的能力#同步:当进程执行到一个IO(等待外部数据,或者下载上传等)的时候 -----------等待:这个就是同步#异步:当进程执行到一个IO(等待外部数据,或者下载上传等)的时候 -----------不等待而去执行其他操作,到数据接收成功再来执行:这个就是异步#同步锁import threadingimport timedef foo(): global num #在每个线程中都能获取这个全