死锁现象与解决方案
- from threading import Thread,Lock,active_count
- import time
- mutexA=Lock() # 锁 1
- mutexB=Lock() # 锁 2
- class Mythread(Thread):
- def run(self):
- self.f1()
- self.f2()
- def f1(self):
- mutexA.acquire()
- print('%s 拿到 A 锁' %self.name)
- mutexB.acquire()
- print('%s 拿到 B 锁' %self.name)
- mutexB.release()
- mutexA.release()
- def f2(self):
- mutexB.acquire()
- print('%s 拿到 B 锁' %self.name)
- time.sleep(1)
- mutexA.acquire()
- print('%s 拿到 A 锁' %self.name)
- mutexA.release()
- mutexB.release()
- if __name__ == '__main__':
- for i in range(10):
- t=Mythread()
- t.start()
- # print(active_count())
- # 死锁现象: 线程 1 拿到一把锁, 线程 2 也拿到一把锁, 线程 1 想要线程 2 的锁, 线程 2 想要线程 1 的锁, 于是就阻塞了, 这说明 2 把锁不能同时 acquire
- # 解决方法如下, 递归锁
- from threading import Thread,Lock,active_count,RLock
- import time
- # mutexA=Lock()
- # mutexB=Lock()
- obj=RLock() #递归锁的特点: 可以连续的 acquire. 其本质其实还是一把锁, 只是把一把锁转换成了 2 把而已
- mutexA=obj
- mutexB=obj
- class Mythread(Thread):
- def run(self):
- self.f1()
- self.f2()
- def f1(self):
- mutexA.acquire()
- print('%s 拿到 A 锁' %self.name)
- mutexB.acquire()
- print('%s 拿到 B 锁' %self.name)
- mutexB.release()
- mutexA.release()
- def f2(self):
- mutexB.acquire()
- print('%s 拿到 B 锁' %self.name)
- time.sleep(1)
- mutexA.acquire()
- print('%s 拿到 A 锁' %self.name)
- mutexA.release()
- mutexB.release()
- if __name__ == '__main__':
- for i in range(10):
- t=Mythread()
- t.start()
- # print(active_count())
死锁现象与递归锁解决方案
开启线程的 2 种方式
- from threading import Thread
- import time
- # 方式一
- def task(name):
- print('%s is running' %name)
- time.sleep(3)
- print('%s is done' %name)
- if __name__ == '__main__':
- t=Thread(target=task,args=('子线程',))
- t.start()
- print('主')
- # 开启并发线程比开启并发进程要快的多, 线程是在进程里开启, 而进程是向操作系统发请求开辟一个新的内存空间
- # 方式二
- # class Mythread(Thread):
- # def run(self):
- # print('%s is running' %self.name)
- # time.sleep(3)
- # print('%s is done' %self.name)
- #
- # if __name__ == '__main__':
- # t=Mythread()
- # t.start()
- # print('主')
开启线程的 2 种方式
01 什么是线程
进程其实不是一个执行单位, 进程是一个资源单位
每个进程内自带一个线程, 线程才是 cpu 上的执行单位
如果把操作系统比喻为一座工厂
在工厂内每造出一个车间 ===启动一个进程
每个车间内至少有一条流水线 ===每个进程内至少有一个线程
线程 =单指代码的执行过程
进程 -资源的申请与销毁的过程
02 进程 vs 线程
1, 内存共享 or 隔离
多个进程内存空间彼此隔离
同一进程下的多个线程共享该进程内的数据
2, 创建速度
造线程的速度要远远快于造进程
- # 主进程等子进程是因为主进程要给子进程收尸
- # 进程必须等待其内部所有线程都运行完毕才结束
- # from threading import Thread
- # import time
- #
- # def task(name):
- # print('%s is running' %name)
- # time.sleep(3)
- # print('%s is done' %name)
- # if __name__ == '__main__':
- # t=Thread(target=task,args=('子线程',))
- # t.start()
- # print('主')
- #
- from threading import Thread,current_thread,active_count,enumerate
- import time
- def task():
- print('%s is running' % current_thread().name)
- time.sleep(3)
- print('%s is done' % current_thread().name)
- if __name__ == '__main__':
- t = Thread(target=task,name='xxx')
- t.start()
- # t.join()
- # print(t.is_alive())
- # print(t.getName())
- # print(t.name)
- # print('主',active_count())
- # print(enumerate())
- # t.join()
- current_thread().setName('主线程')
- print('主',current_thread().name)
线程对象的其他属性与方法
守护线程
- # 守护线程会在本进程内所有非守护的线程都死掉了才跟着死
- # 即:
- # 守护线程其实守护的是整个进程的运行周期 (进程内所有的非守护线程都运行完毕)
- # from threading import Thread,current_thread
- # import time
- #
- #
- # def task():
- # print('%s is running' % current_thread().name)
- # time.sleep(3)
- # print('%s is done' % current_thread().name)
- #
- #
- # if __name__ == '__main__':
- # t = Thread(target=task,name='守护线程')
- # t.daemon=True
- # t.start()
- # print('主')
- from threading import Thread
- import time
- def foo():
- print(123)
- time.sleep(3)
- print("end123")
- def bar():
- print(456)
- time.sleep(1)
- print("end456")
- t1=Thread(target=foo)
- t2=Thread(target=bar)
- t1.daemon=True
- t1.start()
- t2.start()
- print("main-------")
- '''
- 123
- 456
- main-------
- end456
- '''
守护线程
线程 VS 进程
- #1, 线程的开启速度快
- # from threading import Thread
- # from multiprocessing import Process
- # import time
- #
- # def task(name):
- # print('%s is running' %name)
- # time.sleep(3)
- # print('%s is done' %name)
- #
- # if __name__ == '__main__':
- # t=Thread(target=task,args=('子线程',))
- # # t=Process(target=task,args=('子进程',))
- # t.start()
- # print('主')
- #2, 同一进程下的多个线程共享该进程内的数据
- # from threading import Thread
- # import time
- #
- # x=100
- # def task():
- # global x
- # x=0
- #
- # if __name__ == '__main__':
- # t=Thread(target=task,)
- # t.start()
- # # time.sleep(3)
- # t.join()
- # print('主',x)
- # 查看 pid
- from threading import Thread
- import time,os
- def task():
- print(os.getpid())
- if __name__ == '__main__':
- t=Thread(target=task,)
- t.start()
- print('主',os.getpid())
线程 vs 进程
线程互斥锁
- from threading import Thread,Lock
- import time
- mutex=Lock()
- x=100
- def task():
- global x
- # mutex.acquire()
- temp=x
- time.sleep(0.1)
- x=temp-1
- # mutex.release()
- if __name__ == '__main__':
- t_l=[]
- start=time.time()
- for i in range(100):
- t=Thread(target=task)
- t_l.append(t)
- t.start()
- for t in t_l:
- t.join()
- stop=time.time()
- print(x,stop-start)
- # 打印结果为 99 0.1123046875
- # 这说明同一进程下的线程数据是共享的
- View Code
信号量
信号量: 限制的是同一进程下并发执行的任务数 (其本质也是锁, 同一时间可以运行多个任务)
而互斥锁同一时间只能运行一个任务
- # 信号量是控制同一时刻并发执行的任务数
- from threading import Thread,Semaphore,current_thread
- import time,random
- sm=Semaphore(5) # 控制同一个时刻并发运行的多个任务个数
- def task():
- with sm: # with sm 其意思是: sm.acquire() (上锁) sm.release()(解锁)
- print('%s 正在上厕所' %current_thread().name)
- time.sleep(random.randint(1,4))
- if __name__ == '__main__':
- for i in range(20):
- t=Thread(target=task)
- t.start()
- View Code
来源: http://www.bubuko.com/infodetail-2686489.html