1.线程简介
(1)线程概念
- 线程是指进程内的一个执行单元,也是进程内的可调度实体;相当于是进程的一个子任务
- 是操作系统能够进行运算调度的最小单位
(2)线程与进程
- 一个程序中至少有一个进程,而一个进程中也至少有一个线程
2.线程的格式
(1)格式
import threading
threading.Thread(target=None, name=None, args=())
(2)主要参数
参数名 | 作用 |
---|
target | 需要调用的函数名 |
name | 设置线程的名字 |
args | 被调用函数所需要的参数(以元组的形式传入) |
(3)常用方法
方法名 | 功能 |
---|
start() | 启动线程 |
join() | 等待子线程结束 |
setName() | 设置线程名 |
getName() | 返回线程名 |
setDaemon() | 设置守护线程 |
3.线程的创建示例
(1)不设置线程名、被调函数不需要传参
import threading
import time
def task1():
print(threading.current_thread().name,2)
for i in range(1,6):
time.sleep(2)
print("*****我采摘%s个苹果"%i)
def task2():
print(threading.current_thread().name, 3)
for i in range(1,6):
time.sleep(2)
print("$$$$$我采摘%s个苹果"%i)
print(threading.current_thread().name,0)
print(time.ctime())
per1=threading.Thread(target=task1)
per2=threading.Thread(target=task2)
per1.start()
per2.start()
per1.join()
per2.join()
print(time.ctime())
print(threading.current_thread().name,1)
MainThread 0
Fri Jul 3 16:53:59 2020
Thread-1 2
Thread-2 3
*****我采摘1个苹果
$$$$$我采摘1个苹果
*****我采摘2个苹果
$$$$$我采摘2个苹果
*****我采摘3个苹果
$$$$$我采摘3个苹果
$$$$$我采摘4个苹果
*****我采摘4个苹果
$$$$$我采摘5个苹果
*****我采摘5个苹果
Fri Jul 3 16:54:09 2020
MainThread 1
(2)设置线程名、被调函数需要传参
import threading
import time
def task1(a):
print(threading.current_thread().name,2,a)
for i in range(1,6):
time.sleep(2)
print("*****我采摘%s个苹果"%i)
def task2():
print(threading.current_thread().name, 3)
for i in range(1,6):
time.sleep(2)
print("$$$$$我采摘%s个苹果"%i)
print(threading.current_thread().name,0)
print(time.ctime())
per1=threading.Thread(target=task1,name="线程1",args=(10,))
per2=threading.Thread(target=task2)
per2.setName("线程2")
per1.start()
per2.start()
per1.join()
per2.join()
print(time.ctime())
print(threading.current_thread().name,1)
MainThread 0
Fri Jul 3 17:58:03 2020
线程1 2 10
线程2 3
*****我采摘1个苹果
$$$$$我采摘1个苹果
*****我采摘2个苹果
$$$$$我采摘2个苹果
*****我采摘3个苹果
$$$$$我采摘3个苹果
*****我采摘4个苹果
$$$$$我采摘4个苹果
*****我采摘5个苹果
$$$$$我采摘5个苹果
Fri Jul 3 17:58:13 2020
MainThread 1
(3)不写 join()方法
- 主线程不会等待子线程结束,当主线程执行完自己的任务就直接结束,而子线程继续执行自己的任务
import threading
import time
def task1(a):
print(threading.current_thread().name,2,a)
for i in range(1,6):
time.sleep(2)
print("*****我采摘%s个苹果"%i)
def task2():
print(threading.current_thread().name, 3)
for i in range(1,6):
time.sleep(2)
print("$$$$$我采摘%s个苹果"%i)
print(threading.current_thread().name,0)
print(time.ctime())
per1=threading.Thread(target=task1,name="线程1",args=(10,))
per2=threading.Thread(target=task2)
per2.setName("线程2")
per1.start()
per2.start()
print(time.ctime())
print(threading.current_thread().name,1)
MainThread 0
Fri Jul 3 18:19:31 2020
线程1 2 10
线程2 3
Fri Jul 3 18:19:31 2020
MainThread 1
*****我采摘1个苹果
$$$$$我采摘1个苹果
*****我采摘2个苹果
$$$$$我采摘2个苹果
*****我采摘3个苹果
$$$$$我采摘3个苹果
$$$$$我采摘4个苹果
*****我采摘4个苹果
*****我采摘5个苹果
$$$$$我采摘5个苹果
(4)守护线程
- 守护线程就是主线程不管该线程的执行情况,只要其它子线程结束以及主线程执行结束,程序直接结束,守护线程也直接结束
import threading
import time
def task1(a):
print(threading.current_thread().name,2,a)
for i in range(1,6):
time.sleep(2)
print("*****我采摘%s个苹果"%i)
def task2():
print(threading.current_thread().name, 3)
for i in range(1,6):
time.sleep(2)
print("$$$$$我采摘%s个苹果"%i)
print(threading.current_thread().name,0)
print(time.ctime())
per1=threading.Thread(target=task1,name="线程1",args=(10,))
per2=threading.Thread(target=task2)
per2.setName("线程2")
per1.setDaemon(True)
per2.setDaemon(True)
per1.start()
per2.start()
print(time.ctime())
print(threading.current_thread().name,1)
MainThread 0
Sat Jul 4 13:02:58 2020
线程1 2 10
线程2Sat Jul 4 13:02:58 2020
MainThread 1
4.锁线程实例
(1)不加锁
import threading
blance = 0
def access(n):
global blance
blance = blance + n
blance = blance - n
def task(arg, n):
while arg > 0:
try:
access(n)
finally:
arg = arg - 1
t1 = threading.Thread(target=task, args=(40000, 5))
t2 = threading.Thread(target=task, args=(40000, 8))
t1.start()
t2.start()
t1.join()
t2.join()
print(blance)
- 多次运行后,得出的结果分别为:0,0,0,5,0,0,-8,0,5,5,0
- 由上可知,若多个线程不加锁,就有可能多个线程同时修改某一个变量,会将数据改乱,得出的结果会与实际结果不同
(2)加锁
- 通过 threading.RLock() 方法来创建锁,之后通过 acquire() 方法来获取锁,release() 方法释放锁
import threading
blance = 0
lock = threading.RLock()
def access(n):
global blance
blance = blance + n
blance = blance - n
def task(arg, n):
while arg > 0:
lock.acquire()
try:
access(n)
finally:
lock.release()
arg = arg - 1
t1 = threading.Thread(target=task, args=(40000, 5))
t2 = threading.Thread(target=task, args=(40000, 8))
t1.start()
t2.start()
t1.join()
t2.join()
print(blance)