线程与进程的数据共享

10、数据共享

除了上面的通过Queue队列文件进行数据共享外

还可以使用Manager(list列表,dict字典)进行进程之间的共享数据

from multiprocessing import Process,Manager,Lock
def work(data,lock):
	# 1.正常写法
	"""
	lock.acquire()
	# data["count"] -= 1
	data[0] += 1
	lock.release()
	"""
	
	# 2.使用with 语法简化上锁解锁操作
	with lock:
		data[0] += 1
	
if __name__ == "__main__":
	m = Manager()
	# 创建一个共享的字典
	data = m.dict( {
     "count":20000} )
	# 创建一个共享的列表
	data = m.list([1,2,3])
	
	# print(data)
	
	lst = []
	lock = Lock()
	for i in range(100):
		p = Process(target=work,args=(data,lock))
		p.start()
		lst.append(p)
		
	# 确保所有的进程执行完毕,然后在向下运行,打印数据,否则报错;
	for i in lst:
		i.join()
		
	print(data) # [101, 2, 3]

廿三、线程

线程是计算机中调度的最小单位

线程的特点:线程比较轻量级,能干更多的活,一个进程中的所有线程资源是共享的

注:一个进程至少有一个线程在工作

目前配置最高的主机,5万个并发已经是上线

1、线程的基本使用

(1)一份进程资源中可以包含多个线程

(2)多线程的速度远远快于多进程

(3)多线程:共享同一份进程资源

(4)用类定义线程:继承线程父类Thread

from threading import Thread
from multiprocessing import Process
import os

# (1)
def func(num):
	print('当前线程{},所归属的进程id号{}'.format(os.getpid(),num))

for i in range(10):
	# 异步创建10个子线程
	t = Thread(target=func,args=(i,))
	t.start()

# 主线程执行任务
print(os.getpid())

# (2)
import time
def func(num):
    print('当前线程{},所归属的进程id号{}'.format(num, os.getpid()))

if __name__ == "__main__":
    starttime = time.time()
    lst = []
    for i in range(100):
        t = Thread(target=func, args=(i,))
        t.start()
        lst.append(t)
    for i in range(100):
        p = Process(target=func, args=(i,))
        p.start()
        lst.append(p)
        
    for i in lst:
        i.join()
    endtime=time.time()
    print("多线程执行时间:", endtime-starttime)

# (3)
num =1000
def func():
	global num
	num -=1

for i in range(1000):
	t=Thread(target=func)
	t.start()

print(num)

# (4)
class MyThread(Thread):
	def __init__(self,name):
		# 手动调用父类的构造方法
		super().__init__()
		self.name = name

	def run(self):
		time.sleep(1)
		print("当前进程正在执行runing ... " , self.name)
		
if __name__ == "__main__":
	t = MyThread("机器今天会再次爆炸么?")
	t.start()
	print("主线程执行结束 ... ")

2、线程的缺陷

python中的线程可以并发但不能并行;同一个进程下的多个线程不能分开被多个cpu同时执行

原因:

​ 全局解释器锁(Cpython解释器特有)GIL锁:同一时间一个进程下的多个线程只能被一个cpu执行

​ python是解释型语言,不能一次性全部编译成功,不能提前规划,都是临时调度,容易造成cpu执行调度异常,所以加了一把锁叫GIL

实现并行的方法:

​ (1)用多进程间接实现线程的并行

​ (2)换一个Pypy,Jpython解释器

线程分为计算密集型和IO密集型:

​ 计算密集型会大量占用cpu资源,对于python来说负担大

​ IO密集型像网页,爬虫,OA办公,python处理起来就很方便

3、线程的相关函数

(1)is_alive():检测线程是否仍然存在

(2)setName():设置线程名

(3)getName():获取线程名

(4)currentThread().ident:查看线程id号

(5)enumerate():返回目前正在运行的线程列表

(6)activeCount():返回目前正在运行的线程数量

# 
def func():
	time.sleep(1)
if __name__ == "__main__":
	t = Thread(target=func)
	t.start()
	print(t.is_alive()) # False
	print(t.getName())
	t.setName("1234")
	print(t.getName())

# currentThread().ident
def func():
	print("子线程id",currentThread().ident  , os.getpid())

if __name__ == "__main__":
	Thread(target=func).start()
	print("主线程id",currentThread().ident , os.getpid())

# enumerate(),activeCount()
from threading import enumerate
from threading import activeCount # (了解)
def func():
	print("子线程id",currentThread().ident  , os.getpid())
	time.sleep(0.5)
	
if __name__ == "__main__":
	for i in range(10):
		Thread(target=func).start()
	lst = enumerate()
	print( activeCount() )

4、守护线程

注:等待所有线程全部执行完,才终止程序,守护的是所有线程

from threading import Thread
import time
def func1():
	while True:
		time.sleep(0.5)
		print("我是func1")
	
def func2():	
	print("我是func2 start ... ")
	time.sleep(3)
	print("我是func2 end ... ")
	
t1 = Thread(target=func1)
t2 = Thread(target=func2)

# 在start调用之前,设置守护线程
t1.setDaemon(True)

t1.start()
t2.start()

print("主线程执行结束 ... ")

5、线程锁

Lock和信号量Semaphore

保证线程数据安全

注:在创建线程的时候是异步创建,在执行的时候因为Semaphore加了锁,所以线程之间变成同步

# Lock
from threading import Lock,Thread
import time
n = 0

def func1(lock):
	global n
	
	lock.acquire()
	for i in range(1000000):
		# 方法一		
		n -= 1
	lock.release()
	
def func2(lock):
	global n
	# with 自动完成上锁+解锁
	with lock:
		for i in range(1000000):
			# 方法二				
			n += 1

if __name__ == "__main__":
	lst = []
	lock = Lock()
	
	time1 = time.time()
	for i in range(10):
		t1 = Thread(target=func1,args=(lock,))
		t2 = Thread(target=func2,args=(lock,))
		t1.start()
		t2.start()
		lst.append(t1)
		lst.append(t2)
	
	# 等待所有的子线程执行结束之后, 在打印数据
	for i in lst:
		i.join()
	time2 = time.time()
	print("主线程执行结束..." , n ,time2 - time1)

# semaphore
from threading import Semaphore,Thread
import time

def func(i,sm):
	with sm:	
		print(i)
		time.sleep(3)

if __name__ == "__main__":
	sm = Semaphore(5)
	for i in range(20):
		Thread(target=func,args=(i,sm)).start()

你可能感兴趣的:(Python基础)