(并发编程)线程 (理论-创建-lock-属性-守护,与进程的对比)
一、线程理论
1、什么是线程
线程指的是一条流水线的工作过程(执行代码)
进程不是执行单位,是资源单位
一个进程内自带一个线程,线程是执行单位
1、什么是线程
线程指的是一条流水线的工作过程(执行代码)
进程不是执行单位,是资源单位
一个进程内自带一个线程,线程是执行单位
2、进程VS线程
1、同一进程内的线程们共享该进程内资源,不同进程内的线程资源肯定是隔离的
2、创建线程的开销比创建进程要小的多
1、同一进程内的线程们共享该进程内资源,不同进程内的线程资源肯定是隔离的
2、创建线程的开销比创建进程要小的多
3、线程中没有父子关系。相较于子线程、主线程特殊之处在于其代变了主进程的生命周期。
主进程等待子进程结束然后结束,是为子进程回收资源。
主线程等待子线程结束然后结束,是等待这个进程的代码(其他非守护线程)执行完毕。
主线程等待子线程结束然后结束,是等待这个进程的代码(其他非守护线程)执行完毕。
主进程:执行完代码就结束。
主线程:所以子线程结束才结束。
主线程:所以子线程结束才结束。
二、开启线程的两种方式
方式一:导入Thread模块
from threading import Thread
import time
方式一:导入Thread模块
from threading import Thread
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is running' %name)
time.sleep(3)
if __name__ == '__main__':
t=Thread(target=task,args=('egon',))
t.start()
print('主线程')
t=Thread(target=task,args=('egon',))
t.start()
print('主线程')
方式二:创建类继承Thread
from threading import Thread
import time
from threading import Thread
import time
class MyThread(Thread):
def run(self):
print('%s is running' %self.name)
time.sleep(3)
def run(self):
print('%s is running' %self.name)
time.sleep(3)
if __name__ == '__main__':
t=MyThread()
t.start()
print('主线程')
t=MyThread()
t.start()
print('主线程')
三、进程vs线程
1、瞅一瞅PID (Process ID)
from threading import Thread
import time,os
1、瞅一瞅PID (Process ID)
from threading import Thread
import time,os
def task():
print('%s is running' %os.getpid())
time.sleep(3)
print('%s is running' %os.getpid())
time.sleep(3)
if __name__ == '__main__':
t=Thread(target=task,)
t.start()
print('主线程',os.getpid()) #一个进程中的子线程pid相同
t=Thread(target=task,)
t.start()
print('主线程',os.getpid()) #一个进程中的子线程pid相同
2、线程创建开销小
3、同一进程内的多个线程共享该进程内的资源
from threading import Thread
import time,os
from threading import Thread
import time,os
x=1000
def task():
global x
x=0
def task():
global x
x=0
if __name__ == '__main__':
t=Thread(target=task,)
t.start()
t.join()
print('主线程',x) #主线程 0
t=Thread(target=task,)
t.start()
t.join()
print('主线程',x) #主线程 0
四、线程对象的其他方法
from threading import Thread,current_thread,active_count,enumerate
import time,os
from threading import Thread,current_thread,active_count,enumerate
import time,os
def task():
print('%s is running' %current_thread().name) #Thread-1 is running
time.sleep(3)
print('%s is running' %current_thread().name) #Thread-1 is running
time.sleep(3)
if __name__ == '__main__':
t1=Thread(target=task,name='第一个线程')
t2=Thread(target=task,)
t3=Thread(target=task,)
t1.start()
t2.start()
t3.start()
print(t1.is_alive()) #True
print(active_count()) #4
print(enumerate()) #[<_MainThread(MainThread, started 4320768832)>, <Thread(第一个线程, started 123145551912960)>, <Thread(Thread-1, started 123145557168128)>, <Thread(Thread-2, started 123145562423296)>] #当前活跃的线程
print('主线程',current_thread().name) #主线程 MainThread
t1=Thread(target=task,name='第一个线程')
t2=Thread(target=task,)
t3=Thread(target=task,)
t1.start()
t2.start()
t3.start()
print(t1.is_alive()) #True
print(active_count()) #4
print(enumerate()) #[<_MainThread(MainThread, started 4320768832)>, <Thread(第一个线程, started 123145551912960)>, <Thread(Thread-1, started 123145557168128)>, <Thread(Thread-2, started 123145562423296)>] #当前活跃的线程
print('主线程',current_thread().name) #主线程 MainThread
五、守护线程
from threading import Thread,current_thread
import time
from threading import Thread,current_thread
import time
def task():
print('%s is running' %current_thread().name)
time.sleep(3)
print('%s is running' %current_thread().name)
time.sleep(3)
if __name__ == '__main__':
t1=Thread(target=task,name='第一个线程')
t1.daemon = True
t1.start()
t1=Thread(target=task,name='第一个线程')
t1.daemon = True
t1.start()
print('主线程')
from threading import Thread
import time
def foo():
print(123)
time.sleep(5)
print("end123")
import time
def foo():
print(123)
time.sleep(5)
print("end123")
def bar():
print(456)
time.sleep(3)
print("end456")
print(456)
time.sleep(3)
print("end456")
if __name__ == '__main__':
t1=Thread(target=foo)
t2=Thread(target=bar)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------")
t1.start()
t2.start()
print("main-------")
'''
123
456
main-------
end456
'''
123
456
main-------
end456
'''
主进程:执行完代码就结束。
主线程:所以子线程结束才结束。
总结:只要进程内没有可执行的代码守护就结束
主线程:所以子线程结束才结束。
总结:只要进程内没有可执行的代码守护就结束
六、线程互斥锁
from threading import Thread,Lock
import time
from threading import Thread,Lock
import time
mutex=Lock()
x=100
x=100
def task():
global x
mutex.acquire()
temp=x
time.sleep(0.1)
x=temp-1
mutex.release()
global x
mutex.acquire()
temp=x
time.sleep(0.1)
x=temp-1
mutex.release()
if __name__ == '__main__':
start=time.time()
t_l=[]
for i in range(100):
t=Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
start=time.time()
t_l=[]
for i in range(100):
t=Thread(target=task)
t_l.append(t)
t.start()
for t in t_l:
t.join()
print('主',x) #0
print(time.time()-start)
print(time.time()-start)