线程与多线程,线程间数据共享,线程锁解决数据混乱,定时线程,线程通信。
线程:
线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程
多线程:
多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。具有这种能力的系统包括对称多处理机、多核心处理器以及芯片级多处理(Chip-level multithreading)或同时多线程(Simultaneous multithreading)处理器。 [1] 在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理(Multithreading)”。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程(台湾译作“执行绪”),进而提升整体处理性能
_thread模块:低级模块
threading模块:高级模块,对_thread进行了封装
import threading
import random
import time
def run1(num):
print("启动%s子线程1-----%s"%(threading.current_thread().name, num))
time.sleep(random.random()*5)
print("结束%s子线程1-----%s" % (threading.current_thread().name, num))
def run2(num):
print("启动%s子线程2-----%s" % (threading.current_thread().name, num))
time.sleep(random.random() * 5)
print("结束%s子线程2-----%s" % (threading.current_thread().name, num))
if __name__ == "__main__":
# threading.current_thread()得到当前线程对象
# 主线程的名字默认为MainThread
print("主线程%s启动……" % threading.current_thread().name)
#创建线程
th1 = threading.Thread(target=run1, args=(1,), name="th1")
th2 = threading.Thread(target=run2, args=(2,), name="th2")
#启动
th1.start()
th2.start()
#等待子线程结束
th1.join()
th2.join()
print("主线程%s结束……" % threading.current_thread().name)
线程间共享数据:
#多线程和多进程最大的不同在于,多进程中,同一个全局变量,每个子进程各自有一份拷贝,互不影响。而在多线程中,所有变量都由线程共享,所以任何一个变量都可以被任意线程所修改。因此,多个线程同时改变一个变量,容易把内容改乱了
import threading
import random
import time
money = 0
def changeMoney(n):
global money
money = money + n
money = money - n
def run1(num):
for i in range(1000000):
changeMoney(num)
def run2(num):
for i in range(1000000):
changeMoney(num)
if __name__ == "__main__":
#创建线程
th1 = threading.Thread(target=run1, args=(5,), name="th1")
th2 = threading.Thread(target=run2, args=(8,), name="th2")
#启动
th1.start()
th2.start()
#等待子线程结束
th1.join()
th2.join()
print("money = %d"%money)
线程锁解决数据混乱:
问题:两个线程同时一寸一取,可能造成变量值的不对,我们必须保证一个线程在修改money的时候,其他的线程一定不能修改
后期在线程中对变量上锁,但是千万要注意释放锁(自己的锁自己放),否则会造成死锁
import threading
import random
import time
lock = threading.Lock()
money = 0
def changeMoney(n):
global money
money = money + n
money = money - n
def run1(num):
for i in range(1000000):
#获取线程锁,如果已上锁,则阻塞等待锁的释放
lock.acquire()
try:
changeMoney(num)
finally:
#释放锁
lock.release()
def run2(num):
for i in range(1000000):
with lock:
changeMoney(num)
if __name__ == "__main__":
#创建线程
th1 = threading.Thread(target=run1, args=(5,), name="th1")
th2 = threading.Thread(target=run2, args=(8,), name="th2")
#启动
th1.start()
th2.start()
#等待子线程结束
th1.join()
th2.join()
print("money = %d"%money)
ThreadLocal
import threading
import random
import time
# 创建全局ThreadLocal对象
# 每个线程独立的存储空间
# 每个Thread对它都可以读写属性操作,但是互不影响
local = threading.local()
def run1(num):
time.sleep(1)
local.money = 2
print("1-------------", local.money,id(local.money))
def run2(num):
time.sleep(3)
local.money = 3
print("3-------------", local.money,id(local.money))
if __name__ == "__main__":
#创建线程
th1 = threading.Thread(target=run1, args=(5,), name="th1")
th2 = threading.Thread(target=run2, args=(8,), name="th2")
#启动
th1.start()
th2.start()
#等待子线程结束
th1.join()
th2.join()
# print("money = %d"%money)
定时线程:
import time
import threading
def run():
print("sunck is a good man")
if __name__ == "__main__":
# 经常启动5秒后在执行,不会阻塞主线程
th = threading.Timer(5, run)
th.start()
th.join()
线程通信:
import threading
import time
def func():
event= threading.Event()
def run():
for i in range(10):
#阻塞
event.wait()
#重置
event.clear()
print("--------------" + str(i))
th = threading.Thread(target=run)
th.start()
return event
event = func()
for i in range(10):
event.set()
print(i)
time.sleep(1)
print("END")
线程调度:
import threading
import time
#线程条件变量
cond = threading.Condition()
def run1():
with cond:
for i in range(0, 10, 2):
print(threading.current_thread().name+"---"+str(i))
time.sleep(1)
cond.wait()#等待
cond.notify()
def run2():
with cond:
for i in range(1, 10, 2):
print(threading.current_thread().name+"---"+str(i))
time.sleep(1)
cond.notify()#在这里唤醒run1中的 自身再等待
cond.wait()
if __name__ == "__main__":
th1 = threading.Thread(target=run1, name="th1")
th2 = threading.Thread(target=run2, name="th2")
th1.start()
th2.start()
th1.join()
th2.join()
print("END")