线程全局修改

x = 100
def func1():
global x
print(x)
changex()
print(x)
def changex():
global x
x = 50 func1() """
100 50
"""

线程锁

from threading import Thread, Lock

x = 0
mutex = Lock()
def task():
global x
mutex.acquire() #加了锁之后就能保证每次只有一个运行,就不会出现数据丢失现象,不过效率会降低
for i in range(100000):
x = x + 1
"""
如果不加锁,那么(以下的情况属于假设):
t1 的 x 刚拿到0(属于IO) 保存好状态,这时候CPU切换给t2运行。
t2 的 x拿到 0 并进行+1 操作 这时候x是1(运行完CPU切换)
t1 又获得运行了 x = 0 并进行+1操作 这时候x也是1
****************************
经过上面三步,是加了2次1,而真实运算出来的应该是+2,实际上只是加了1
这就是为什么不加锁本来应该是300000,但是实际上却小于这个数的原因
这就会产生数据安全问题
"""
mutex.release() if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task) t1.start()
t2.start()
t3.start() t1.join()
t2.join()
t3.join()
print(x)

死锁问题

from threading import Thread,Lock

lock1 = Lock()
# lock2 = lock1 #这种情况相当于只有一把锁,
# 所以抢到了锁1之后没办法再抢锁2了,就会卡在(Thread-1 抢到了锁1)
lock2 = Lock()
class DeadLock(Thread):
def run(self):
self.task1()
self.task2() def task1(self):
lock1.acquire()
print(f'{self.name} 抢到了锁1')
lock2.acquire()
print(f'{self.name} 抢到了锁2')
lock2.release()
print(f'{self.name} 释放了锁2')
lock1.release()
print(f'{self.name} 释放了锁1')
def task2(self):
# 这里如果抢锁2,就会出现死锁现象,就会卡在这
# lock2.acquire()
# print(f'{self.name} 抢到了锁2')
# 这里如果抢锁1,就不会出现死锁现象,会一直运行下去
# lock1.acquire()
# print(f'{self.name} 抢到了锁1')
lock2.acquire()
print(f'{self.name} 抢到了锁2')
lock1.release()
print(f'{self.name} 释放了锁1')
lock2.release()
print(f'{self.name} 释放了锁2') for i in range(3):
t = DeadLock()
t.start() *******死锁问题********
###两个线程
# 线程1拿到了(锁2),想要往下执行需要(锁1),
# 线程2拿到了(锁1),想要往下执行需要(锁2),
# 互相都拿到了彼此想要往下执行的必需条件,互相都不放手里的锁

递归锁

from threading import Thread,RLock
'''
递归锁 在同一个线程内可以被多次acquire
如何释放 内部相当于维护了一个计数器
也就是说同一个线程 acquire了几次
就要release几次 '''
lock1 = RLock()
lock2 = lock1
class Recursion(Thread):
def run(self):
self.task1()
self.task2() def task1(self):
lock1.acquire()
print(f'{self.name}抢到了 锁1')
lock2.acquire()
print(f'{self.name}抢到了 锁2')
lock1.release()
print(f'{self.name}释放了 锁1')
lock2.release()
print(f'{self.name}释放了 锁2')
def task2(self):
lock1.acquire()
print(f'{self.name}抢到了 锁1')
lock2.acquire()
print(f'{self.name}抢到了 锁2')
lock1.release()
print(f'{self.name}释放了 锁1')
lock2.release()
print(f'{self.name}释放了 锁2') for i in range(3):
t = Recursion()
t.start() #可以正常执行,不会出现差错

信号量

from threading import Thread,currentThread,Semaphore
import time def task():
sm.acquire()
time.sleep(2)
print(f'{currentThread().name} is running!')
sm.release() sm = Semaphore(5) #(可以一次性发5个,信号量就是自定义最大连接数5个)
for i in range(15):
t = Thread(target=task)
t.start()
"""
会分3组, 每组5个打印出来
"""

GIL(全局解释器锁)

"""
###在Cpython解释器中有一把GIL(全局解释器锁),GIL锁本质是一把互斥锁。 导致了同一个进程下,同一时间只能运行一个进程,无法利用多核优势,同一进程
下多个线程只能实现并发不能实现并行。 为什么要有GIL?
因为Cpython自带的垃圾回收机制不是线程安全的,所以要有GIL锁。 导致了同一进程下,同一时间只能运行一个线程,无法利用多核优势。 分析:
我们有四个任务需要处理,处理方式肯定要玩出并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程 """
#******计算密集型******
#推荐使用多进程
from threading import Thread
from multiprocessing import Process
import time def work1():
res = 0
for i in range(100000000):
res *= i if __name__ == '__main__':
t_list = []
start = time.time()
for i in range(5):
t = Process(target=work1)
# t = Thread(target=work1())
t.start()
t_list.append(t)
for t in t_list:
t.join()
end = time.time()
print('多进程', end - start) #多进程 22.06749701499939
# print('多线程', end - start) #多线程 41.195727586746216 ******IO密集型******
#推荐使用多线程 from threading import Thread
from multiprocessing import Process
import time def task1():
x = 1+1
time.sleep(3) if __name__ == '__main__':
t_list = []
start = time.time()
for i in range(4):
# t = Thread(target=task1)
t = Process(target=task1)
t_list.append(t)
t.start()
for t in t_list:
t.join()
end = time.time()
# print('多线程', end - start) #多线程 3.002215623855591
print('多进程', end - start) #多进程 3.8354334831237793

最新文章

  1. Tomcat:Custom a common error page valve for all web application in tomcat
  2. Ubuntu下vim的配置
  3. Django 后台搭建
  4. Java之 AtomicInteger
  5. 【JS】Beginner2:Variables & Data
  6. SQL中什么叫模式
  7. 计蒜客 取数游戏 博弈+dp
  8. PHP自动加载机制
  9. luogu P2071 座位安排
  10. sql 判断两条数据库查询语句结果是否有重复
  11. 在ionic中使用短信验证码倒计时
  12. QT linux
  13. MongoDB-Java的两个基本操作Upsert和insertMany
  14. jps -- process information unavailable
  15. UE4 材质Lerp节点解疑
  16. 【Tomcat】Tomcat安装及Eclipse配置教程
  17. WebStorm新创建项目介绍
  18. 【Linux技术】常用的Linux系统调用
  19. Python面试题之装饰器漫谈
  20. apache ftp server的外网访问问题

热门文章

  1. 实现100以内的素数输出(Python与C++对比)
  2. 强烈推荐一个和朋友远程桌面的软件teamviewer
  3. ECMAScript 初探 - 基础篇
  4. Reflector调试dll功能
  5. 《 .NET并发编程实战》阅读指南 - 第13章
  6. .Net工具类--表达式目录树解析DataReader和DataTable
  7. C# 操作LDAP
  8. [Silverlight 4] 參數的傳遞方法
  9. SqlDbx连接oracle(无需安装Oracle客户端)
  10. Python——全国瓜子二手车数据分析