线程

内容梗概:
1.线程的定义,创建以及threading模块
2.线程的一些其他方法
3.进程与线程创建的效率对比
4.线程间的数据共享
5.死锁现象
6.守护线程,事件,信号量

1.线程的定义以及创建
定义:
进程是资源分配的最小单位,线程是CPU调度的最小单位.每一个进程中至少有一个线程。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
线程与进程的区别:
   1)地址空间和其它资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
   2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。(就类似进程中的锁的作用)
   3)调度和切换:线程上下文切换比进程上下文切换要快得多。
   4)在多线程操作系统中(现在咱们用的系统基本都是多线程的操作系统),进程不是一个可执行的实体,真正去执行程序的不是进程,是线程,你可以理解进程就是一个线程的容器。


线程的创建以及threading模块:
创建方式1:
import os,time
from threading import Thread
def func(num):
time.sleep(1)
print('我是子线程,我的pid是',os.getpid())
print("hei,girl")
print(num)
if __name__ == '__main__':
t = Thread(target=func,args=(3,))
t.start()
print('主线程的pid',os.getpid()) #主线程和子线程都在同一个进程中

创建方式2:
import time
from threading import Thread
class mythread(Thread):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
time.sleep(0.5)
print("Hei girl,I am %s"%self.name)
if __name__ == '__main__':
t = mythread("王大锤")
t.start()
print('开始等待子线程了')
t.join() #等待子线程结束才继续往下执行主线程
print('主线程结束')


2.线程的一些其他方法
import time,threading
from threading import current_thread,Thread
def func(num):
time.sleep(1)
print("子线程名",current_thread().getName())
print("子线程id", current_thread().ident)

pass
if __name__ == '__main__':
t = Thread(target=func,args=(5,))
t.start()
print(threading.enumerate())
print(threading.activeCount())


3.进程与线程创建的效率对比
import time
from threading import Thread
from multiprocessing import Process
def func():
print('Hei girl')
if __name__ == '__main__':
t_list = []
t_s_t = time.time()
for i in range(100):
t = Thread(target=func, )
t_list.append(t)
t.start()
[tt.join() for tt in t_list]
t_e_t = time.time()
t_dif_t = t_e_t - t_s_t

p_list = []
p_s_t = time.time()
for i in range(100):
p = Process(target=func, )
p_list.append(p)
p.start()
[pp.join() for pp in p_list]
p_e_t = time.time()
p_dif_t = p_e_t - p_s_t
print('多线程的时间>>>', t_dif_t)
print('多进程的时间>>>', p_dif_t)
# 多线程的时间>>> 0.019013404846191406
# 多进程的时间>>> 4.62909722328186
总结:创建进程很慢,所需资源较多,而创建线程很快,不需要什么资源,且线程内数据共享


4.线程之间的数据共享

4.1.线程之间的数据是可以共享的,但是不安全的(要保证安全需要加锁)
import time
from threading import Thread,Lock

num = 100
def func():
global num
lock.acquire()
tep = num
time.sleep(0.01)
tep = tep - 1
num = tep
lock.release()

if __name__ == '__main__':
lock = Lock()
t_list = []
for i in range(100):
t = Thread(target=func, )
t_list.append(t)
t.start()
[tt.join() for tt in t_list]
print('主线程的num',num)


5.死锁现象
可采用递归锁解决
import time
from threading import Thread,Lock,RLock

def func1(lock_A,lock_B):
lock_A.acquire()
time.sleep(0.5)
print('alex拿到了A锁')
lock_B.acquire()
print('alex拿到了B锁')
lock_B.release()
lock_A.release()

def func2(lock_A,lock_B):
lock_B.acquire()
print('taibai拿到了B锁')
lock_A.acquire()
print('taibai 拿到了A锁')
lock_A.release()
lock_B.release()

if __name__ == '__main__':
lock_A = Lock() #普通锁这样会产生死锁
lock_B = Lock()
lock_A = lock_B = RLock() #采用递归锁可解决死锁现象
t1 = Thread(target=func1,args=(lock_A,lock_B))
t2 = Thread(target=func2,args=(lock_A,lock_B))
t1.start()
t2.start()



6.守护线程,事件,信号量
6.1守护线程
tips:记住 主线程需等待非守护线程执行完毕才会结束
import time
from threading import Thread
from multiprocessing import Process
def func1():
time.sleep(3)
print("线程1结束啦")

def func2():
time.sleep(2)
print("线程2结束啦")
if __name__ == '__main__':
t1 = Thread(target=func1)
t2 = Thread(target=func2)
# t1.daemon = True
t1.start()
t2.start()
print("主线程结束啦")

#和守护进程对比
p1 = Process(target=func1, )
p2 = Process(target=func2, )
p1.daemon = True
p2.daemon = True
p1.start()
p2.start()

通过上面的对比发现:
1.守护进程,主进程代码运行完毕后,守护进程会一起结束,而主进程会等非守护进程结束才真正结束
2.守护线程,(主线程需等待非守护线程执行完毕才会结束),即主线程代码运行完了,也不会直接结束守护线程,而要等其他非守护线程执行完,主线程结束,才会结束守护线程


4.2事件
跟进程的事件基本一致

from threading import Thread,Event

e = Event() #默认是False,

print(e.isSet())
print('开始等啦')
e.set() #将事件对象的状态改为True
print(e.isSet())
e.clear() #将e的状态改为False

e.wait() #如果e的状态为False,就在这里阻塞
print('大哥,还没完事儿,你行')

4.3信号量
import time
import random
from threading import Thread,Semaphore

def func(i,s):
s.acquire()
print('客官%s里边请~~' % i)
time.sleep(random.random())
s.release()
if __name__ == '__main__':
s = Semaphore(4) #上锁,但允许一次四个人使用锁
for i in range(10):
t = Thread(target=func,args=(i+1,s))
t.start()
posted @ 2018-11-30 17:42  Mixtea  阅读(145)  评论(0编辑  收藏  举报