并发收尾数据库汇总
内容概要
- 线程
- GIL全局解释锁
- 多线程与多进程
- 死锁现象
- 进程池与线程池
- 协程
- MySQL
线程
-
线程理论
可以把进程看成一个工厂,而线程是工厂里面的一条条流水线真正干活的人
-
创建线程的两种方法
from threading import Thread # 方式一 # def task(name): # print("芜湖 %s" % name) # # # """ # 创建线程可以不写到 main 方法里面 # 但是 建议写到里面 因为 到时候进程线程 写杂了 # # """ # # if __name__ == '__main__': # t = Thread(target=task,args=("jason",)) # t.start() # 方式二 def task(name): print("芜湖 %s" % name) class MyThread(Thread): def run(self): task("jason") obj = MyThread() obj.start() -
线程的诸多特性
from threading import Thread, current_thread def task(name): print("芜湖", name) print(current_thread()) # 查看线程号 t1 = Thread(target=task, args=('jason',)) t2 = Thread(target=task, args=('jason',)) t1.start() # 创建并运行进程 t2.start() t1.join() # 等子线程运行完在运行 主线程 t1.is_alive() -
守护线程
""" 无论是进程还是线程,都遵守:守护XX会等主XX运行完毕被销毁。需强调的是:运行完毕并非终止运行 主进程在主进程的代码运行结束就已经算运行完毕了(守护进程在此时被回收了),然后主进程会一直等非守护的子进程运行完毕回收子进程的资源(否则会产生僵尸进程),才会结束 主线程在其他非守护线程运行结束后才算运行完毕(守护线程在此时才结束) """# from threading import Thread # import time # # def task(name): # time.sleep(2) # print("芜湖", name) # def work(): # time.sleep(3) # print("撒大大") # # if __name__ == '__main__': # # t1 = Thread(target=task, args=('jason',)) # t2 = Thread(target=work) # t1.daemon = True # t1.start() # t2.start() # print("主") from multiprocessing import Process import time def task(name): print("开始") time.sleep(2) print("芜湖", name) def work(): time.sleep(3) print("撒大大") if __name__ == '__main__': p1 = Process(target=task, args=('jason',)) p2 = Process(target=work) p1.daemon = True p1.start() p2.start() time.sleep(0.2) print("主")
GIL全局解释锁
"""
GIL全局解释锁 只有CPython才有
在多线程的情况下 可能会导致 数据值的引用计数错乱
对一个增加一个数据值的引用计数
可能会增加1次 而不是两次
删除的可能只想删除一次引用计数可能直接把这个数字回收掉了
"""
多线程与多进程对比
情况一:
单个CPU
多个CPU
情况二:
IO密集型
计算密集型
1.单个CPU
IO密集型
多进程 需要申请内存空间
多线程 不需要
而且 不管一个CPU 还是多个CPU 遇到IO 都会阻塞
ps:多线程有优势
计算密集型
多进程
申请内存 耗时间
多线程
直接执行
在单个CPU的情况下 线程优势大
2.多个CPU
IO密集型
多进程 需要申请内存空间
多线程 不需要
而且 不管一个CPU 还是多个CPU 遇到IO 都会阻塞
计算密集型
多进程
多个CPU同时运行
申请内存 耗时间
多线程
还只是一个CPU 跑
在多个CPU下
IO密集型 多线程有优势
计算密集型 多进程有优势
死锁现象
所谓的死锁:是指两个或者两个以上的进程或者线程在执行过程中,因为争夺资源而造成的一种相互等地的现象,若无外力作用,他们都将无法进行下去。此时称系统处于死锁状态或者系统产生了死锁 这些永远互相等待的进程称之为死锁
申请两把锁 锁A 和锁B 开两个线程 线A和线B
让线A抢锁A 在抢锁B 然后释放锁B 在释放锁A
在让线A 抢锁B在抢锁A 然后释放锁A 在释放锁B
然后让线B执行
这时当线A第二次抢A锁 线B抢过A去抢B锁
线A在等 锁A释放 线B在等 锁B释放
这就造成了死锁
import time
from threading import Thread, Lock
def task(mutes_A, mutes_B):
mutes_A.acquire()
print("抢A锁")
mutes_B.acquire()
print("抢B锁")
mutes_B.release()
print("释放B锁")
mutes_A.release()
print("释放A锁")
def work(mutes_A, mutes_B):
mutes_B.acquire()
print("抢B锁")
# time.sleep(2)
mutes_A.acquire()
print("抢A锁")
mutes_A.release()
print("释放A锁")
mutes_B.release()
print("释放B锁")
def run(mutes_A, mutes_B):
task(mutes_A, mutes_B)
work(mutes_A, mutes_B)
mutes_A = Lock()
mutes_B = Lock()
for i in range(5):
t = Thread(target=run, args=(mutes_A, mutes_B))
t.start()
"""
不加 time.sleep(2)
抢A锁
抢B锁
释放B锁
释放A锁
抢B锁
抢A锁
释放A锁
释放B锁
抢A锁
抢B锁
释放B锁
释放A锁
抢B锁
抢A锁
释放A锁
释放B锁
抢A锁
抢B锁
释放B锁
释放A锁
抢B锁
抢A锁
释放A锁
....
"""
进程池与线程池
进程池
就是提前创建好一些进程 以后就拿这几个进程用了
线程池
就是提前创建好一些线程 以后拿着着几个线程用
# from concurrent.futures import ProcessPoolExecutor
# from multiprocessing import current_process
# pool = ProcessPoolExecutor(5)
#
#
# def task():
# print("芜湖", current_process().pid)
# return "11"
#
# def work(a):
# print(a.result())
#
#
#
# if __name__ == '__main__':
# for i in range(1000):
# pool.submit(task).add_done_callback(work)
from concurrent.futures import ThreadPoolExecutor
from threading import current_thread
pool = ThreadPoolExecutor(5)
def task():
print("芜湖", current_thread())
return "11"
def work(a):
print(a.result())
if __name__ == '__main__':
for i in range(10000): # 回调函数
pool.submit(task).add_done_callback(work)
协程
"""
进程是资源单位
线程是执行单位
协程是让单线程实现并发(效率高)
协程是程序员意淫出来的东西
在代码的层面欺骗CPU让CPU以为我们代码里面没有IO操作
实际上IO操作被我们写的代码检测到 一旦有 立即让代码执行别的
核心:自己写代码完成 切换 + 保存状态
"""
import time
import gevent
from gevent import monkey; monkey.patch_all()
from gevent import spawn
def task():
print("开始 task")
time.sleep(4)
print("task over")
def work():
print("running work")
time.sleep(3)
print("work over")
if __name__ == '__main__':
start_time = time.time()
s1 = spawn(task)
s2 = spawn(work)
gevent.joinall([s1,s2])
print(time.time() - start_time)
MySQL
-
数据库简介
-
关系型数据库
有固定的表结构
数据之间课可以建立数据库层面的关系
Mysql、 Oracle、 MariaDB、PostgreSQL
sqlite、db2、
-
非关系型数据
没有固定的表结构
数据之间无法建立数据库层面的关系
redis、mongoDB、memcache
-
-
SQL与NoSQL
数据库服务端是可以服务多种类型客户端
客户端可以自己开发 也可以是python也可以是java代码编写
SQL
操作关系型数据库语言
NoSQL
操作非关系型数据库语言
-
基本SQL语句
创建数据库 create database 库名; show databases; 查看所有库 show create database 库名; 创建表 crease table 表名( 字段名 字段类型(数字) 约束条件, 字段名 字段类型(数字) 约束条件 ); show tables; show create table 表名; 数据操作 select * from 表名; insert into 表名(字段名) values(数据值); update 表名 set 字段名 = 值 where 筛选条件; delete from 表名 where 筛选条件; -
数据库引擎
show engines;
-
MySAM
MySQL5.5之前默认的存储引擎
存储数据的速度快 但是功能少 安全性低
-
InnoDB
MySQL5.5之后默认的存储引擎
支持事务、行锁、外键等操作 存储速度没有MyISAM快 但是安全性更高
-
Memory
基于内存存取数据 仅用于临时数据存取
-
BlackHole
任何写进去的数据都会立刻消失
-
-
创建表的完整语法
create table 表名( 字段名 字段类型(数字) 约束条件 ); 1.字段名 和字段类型 必须有 2.数字和约束条件可选 3.约束条件可以写多个 空格隔开即可 4.最后一行结尾不能加逗号 -
字段类型之整型
tinyint 1bytes smallint 2bytes int 4bytes bigint 8bytes -
字段类型之浮点型
float double decimla 区别只有精确度 float < double < decimal -
字段类型之字符串
char 定长 varchart 变长 -
字段类型之枚举与集合
-
枚举(多选一)
create table b1( id int primary key auto_increment, gender enum('男','女') ); -
集合(多选)
create table b2( id int primary key auto_increment, hobby set('足球','篮球','桌球') );
-
-
字段类型之日期类型
datatime 年月日时分秒 time 时分秒 data 年月日 year 年 -
无符号、零填充
unsigend 无符号 zerofill 零填充 -
非空
not null -
默认值
defale -
唯一值
unique -
主键
primary key -
自增
auto_increment 一般与主键连用 -
外键
外键字段
可以建立数据与数据之间的联系
-
关系判断
关系总共有四种
一对多
多对多
一对一
没有关系
关系的判断可以采用
换位思考原则create table c1( id int primary key auto_increment, ); create table c2( id int primary key auto_increment, c1_id int, foreign key(c1_id) references c1(id) on update cascade # 级联修改 on delete cascade # 级联删除 ); """ 外键其实是强耦合 不符合解耦合特征 所以很多时候 实际项目中 当表出现较多的情况 我们可能不会使用外键 而是使用代码建立逻辑层面的 """ -
查询关键字之where筛选
select * from emp where id>= 3, id <=6; -
查询关键字之group by 分组
select post from emp group by post -
查询关键字之having过滤
""" 分组之前用 where 分组之后用 having """ select post, avg(salary) from emp group by post having avg(salary) > 10000; -
distinct去重
""" 可以写一个字段 也可以写多个字段 """ select distinct name from emp; """ 对 name 字段的数据去重 """ select distinct name, age from emp; """ 对 name 跟 age 合起来的数据 去重 """ -
查询关键字之 order by 排序
1. 可以单个字段排序 select * from emp order by name; 2.也可以是多个字段排序 select * from emp order by age, salary desc; 先按age 排序 如果age里面一样 那些一样的数据 按salary 降序排 -
查询关键字之limit分页
select * from emp limit 5; 查看前5条数据 select * from emp limit 5,5; 查看从第5条数据后的5条数据 -
查询关键字之regexp正则表达式
select * from emp where name regexp '^j.*(n|y)$';

浙公网安备 33010602011771号