有了GIL还是会出现数据不安全,所以还是要用锁

import time

from threading import Thread,Lock

n = 100

def func(lock):

  global n

  with lock:

    tmp = n-1

    n = tmp

l = []

lock = Lock()

for i in range(100):

  t = Thread(target = func,args = (lock,))

  t.smxtart()

  l.append(t)

for t in l:t.join()

print(n)

 

dis模块(判断数据是否安全)

import dis

n = 1

def func():

  n = 100

  n -= 1

dis.dis(func)

 

 

 

死锁现象

  死锁不是时刻发生的,有偶然的情况,每一个线程中不止一把锁,并且套着使用

解决死锁的方案

  如果某一件事情需要两个资源同时出现,那么不应该将两个资源通过两把锁控制,而是看做是一个资源,用一把锁控制,先临时解决,然后找到死锁原因,再去修改(科学家吃面条)(递归锁也能解决死锁现象)。

出现死锁现象

# def eat1(name):
# noodle_lock.acquire()
# print('%s拿到面条了'%name)
# fork_lock.acquire()
# print('%s拿到叉子了'%name)
# print('%s开始吃面'%name)
# time.sleep(0.2)
# fork_lock.release()
# print('%s放下叉子了' % name)
# noodle_lock.release()
# print('%s放下面了' % name)
#
# def eat2(name):
# fork_lock.acquire()
# print('%s拿到叉子了' % name)
# noodle_lock.acquire()
# print('%s拿到面条了' % name)
# print('%s开始吃面' % name)
# time.sleep(0.2)
# noodle_lock.release()
# print('%s放下面了' % name)
# fork_lock.release()
# print('%s放下叉子了' % name)
#
# Thread(target=eat1,args=('alex',)).start()
# Thread(target=eat2,args=('wusir',)).start()
# Thread(target=eat1,args=('太白',)).start()
# Thread(target=eat2,args=('宝元',)).start()
解决死锁
# lock = Lock()
# def eat1(name):
# lock.acquire()
# print('%s拿到面条了'%name)
# print('%s拿到叉子了'%name)
# print('%s开始吃面'%name)
# time.sleep(0.2)
# lock.release()
# print('%s放下叉子了' % name)
# print('%s放下面了' % name)
#
# def eat2(name):
# lock.acquire()
# print('%s拿到叉子了' % name)
# print('%s拿到面条了' % name)
# print('%s开始吃面' % name)
# time.sleep(0.2)
# lock.release()
# print('%s放下面了' % name)
# print('%s放下叉子了' % name)
#
# Thread(target=eat1,args=('alex',)).start()
# Thread(target=eat2,args=('wusir',)).start()
# Thread(target=eat1,args=('太白',)).start()
# Thread(target=eat2,args=('宝元',)).start()



递归锁(RLock)
在同一个线程中可以无限次acquire,但是要想在其他线程中也acquire,必须先在自己线程中添加和acquire次数相同的release
import time
noodle_lock = fork_lock = RLock()
def eat1(name):
  noodle_lock.acquire()
  print('%s拿到了面条'%name)
  frok_lock.aquire()
  print('%s拿到了叉子'%name)
  print('%s开始吃面'%name)
  time.sleep(0.2)
  fork_lock.release()
  print('%s放下叉子'%name)
  noodle_lock.release()
  print('%s放下面条'%name)
def eat2(name):
  fork_lock.acquire()
  print('%s拿到了叉子'%name)
  noodle_lock.acquire()
  print('%s拿到了面条'%name)
  print('%s开始吃面'%name)
  time.sleep(0.2)
  fork_lock.release()
  print('%s放下叉子'%name)
  noodle_lock.release()
  print('%s放下面条'%name)
Thread(target = eat1,args = ('alex',)).start()
Thread(target = eat1,args = ('wusir',)).start()
Thread(target = eat1,args = ('taibai',)).start()
Thread(target = eat1,args = ('baiyuan',)).start()

线程 信号量(Semaphore)
import time
from threading import Semaphore,Thread

def func(name,sem):
sem.acquire()
print(name,'start')
time.sleep(1)
print(name,'stop')
sem.release()

sem = Semaphore(5)
for i in range(20):
Thread(target=func,args=(i,sem)).start()
进程池
  有1000个任务,一个进程池中有5个进程,所有的1000个任务会多次利用这五个进程来完成任务
信号量
  有1000个任务,有1000个线程、进程所有的1000个任务由于信号量的控制,只能5个5个的执行




线程事件 (Event)
  wait()阻塞 事件内部标识为True就停止阻塞
控制标识
  set #True
  clear  #False
  is_set #判断是不是True


连接数据库(用事件)
import time
import random
from threading import Thread,Event
def connect_sql(e):
count = 0
while count < 3:
e.wait(0.5)
if e.is_set():
print('连接数据库成功')
break
else:
print('数据库未连接成功')
count += 1
F
def test(e):
time.sleep(random.randint(0,3))
e.set()

e = Event()
Thread(target=test,args=(e,)).start()
Thread(target=connect_sql,args=(e,)).start()



线程条件()
  wait 阻塞
  notify(n) 给信号
  假如现在有20个线程,所有的线程都在wait这里阻塞,nptify(n)n传了多少,那么wait这边就能收获得到多少个解除阻塞的通知

import threading

def run(n):
con.acquire()
con.wait()
print("run the thread: %s" % n)
con.release()

if __name__ == '__main__':

con = threading.Condition()
for i in range(10):
t = threading.Thread(target=run, args=(i,))
t.start()

while True:
inp = input('>>>')
if inp == 'q':
break
con.acquire()
con.notify(int(inp))
con.release()
print('****')

设置某个条件
如果满足这个条件 就可以释放线程
监控测试我的网速
20000个任务
测试我的网速 /系统资源
发现系统资源有空闲,我就放行一部分任务




线程定时器(Timer)
from threading import Timer

def func():
print('执行我啦')

t = Timer(3,func)      #参数3为3秒,就是等待3秒在执行子线程
            # 现在这个时间点我不想让它执行,而是预估一下大概多久之后它执行比较合适
t.start()
print('主线程的逻辑')




线程队列(Queue) #先进先出
q = queue.Queue()
线程栈(LifoQueue)  #先进后出
lfq = queue.LifoQueue()   # 栈
lfq.put(1)
lfq.put(2)
lfq.put(3)
print(lfq.get())
print(lfq.get())
print(lfq.get())

优先级队列(PriorityQueue) #根据第一个值的大小来排定优先级(ascii码越小,优先级越高)
q = queue.PriorityQueue()
q.put((2,'a'))
q.put((1,'c'))
q.put((1,'b'))
print(q.get())

线程池
concurrent.futures




  
  

 

posted on 2018-12-12 22:53  汩汩-咕咚  阅读(142)  评论(0编辑  收藏  举报