多任务-线程

版权声明:属本人原创内容,转载需声明。 https://blog.csdn.net/JJandYY135/article/details/83004182
  • 多任务是指操作系统可以同时运行多个程序。比如你可以在一台电上同时听歌,用pycharm写程序还可以用谷歌浏览器上网。

现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?

答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。

真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。

  • 并发:假的多任务
  • 并行:真的多任务

并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的


yy_01_没有多任务的程序

import time


def sing():
	"""唱歌 5秒钟"""

	for i in range(5):
		print("---正在唱歌---")
		time.sleep(1)

def dance():
	"""跳舞 5秒钟"""

	for i in range(5):
		print("---正在跳舞---")
		time.sleep(1)

def main():
	sing()
	dance()


if __name__ == '__main__':
	main()

yy_02_使用多任务(线程)的程序

import time
import threading


def sing():
	"""唱歌 5秒钟"""

	for i in range(5):
		print("---正在唱歌---")
		time.sleep(1)

def dance():
	"""跳舞 5秒钟"""

	for i in range(5):
		print("---正在跳舞---")
		time.sleep(1)

def main():
	t1 = threading.Thread(target=sing)
	t2 = threading.Thread(target=dance)
	t1.start()
	t2.start()
	
if __name__ == '__main__':
	main()

yy_03_让某些线程先执行

import threading
import time

def test1():

	for i in range(5):
		print("1----%d--1" % i)

def test2():

	for i in range(5):
		print("2----%d--2" % i)


def main():

	t1 = threading.Thread(target=test1)
	t2 = threading.Thread(target=test2)
	
	t1.start()
	time.sleep(1)
	print("---1---")
	
	t2.start()
	time.sleep(1)
	print("---2---")

	print("执行完毕")

if __name__ == '__main__':
	main()

yy_04_循环查看当前运行的线程

import threading
import time

def test1():

	for i in range(5):
		print("1----%d--1" % i)
		time.sleep(1)

	# 如果创建Thread时执时的函数,运行结束,那么就意味着,这个子线程结束了。


def test2():

	for i in range(10):
		print("2----%d--2" % i)
		time.sleep(1)


def main():

	t1 = threading.Thread(target=test1)
	t2 = threading.Thread(target=test2)
	
	t1.start()
	t2.start()
	
	while True:
		# enumerate()打印下标
		if len(threading.enumerate()) <= 1:
			break
		
		print(threading.enumerate())

		time.sleep(1)


		


if __name__ == '__main__':
	main()

yy_05_验证创建线程以及运行时间

import threading
import time

def test():

	for i in range(5):
		print("1----%d----1" % i)
		time.sleep(1)

def main():
	# 验证什么时候开始创建子线程
	# 测试1:在创建Thread之前打印线程数
	print(threading.enumerate())

	t1 = threading.Thread(target=test)
	# 测试2:在创建Thread之后打印线程数
	print(threading.enumerate())

	t1.start()
	# 测试3:在start之后打印线程数
	
	while True:

		if len(threading.enumerate()) <= 1:
			break
		
		print(threading.enumerate())

		time.sleep(1)
	

if __name__ == '__main__':
	main()
  • 未完待续

yy_06_函数里面修改全局变量

gl_num = 100
gl_list = [1, 2]
gl_tuple = (1, 2)

def test():

	global gl_num
	gl_num += 100


def test2():
	gl_list.append(666)


def test3():

	global gl_tuple
	gl_tuple = (1, 2, 777)

print(gl_num)
print(gl_list)
print(gl_tuple)

test()
test2()
test3()

print(gl_num)
print(gl_list)
print(gl_tuple)

yy_07_多线程共享全局变量

import threading


gl_num = 100


def test1():
	global gl_num
	gl_num += 1
	print("---test1----gl_num = %d" % gl_num)	


def test2():
	print("---test2----gl_num = %d" % gl_num)	


def main():

	t1 = threading.Thread(target=test1)
	t2 = threading.Thread(target=test2)

	t1.start()
	t2.start()

	print(gl_num)


if __name__ == '__main__':
	main()

yy_08_args方法

import threading


gl_list = [1, 2]


def test1(lis):
	lis.append(3)
	print("---test1----gl_list = %s" % lis)	


def test2(lis):
	print("---test2----gl_list = %s" % lis)	


def main():

	t1 = threading.Thread(target=test1, args=(gl_list,))  # 元组只有一个参数要加,号
	t2 = threading.Thread(target=test2, args=(gl_list,))

	t1.start()
	
	
	t2.start()
	

	print(gl_list)


if __name__ == '__main__':
	main()



yy_09_共享全局变量问题-资源竞争

import threading
import time


gl_num = 0


def test1(lis):
	global gl_num
	for i in range(lis):
		gl_num += 1  # 底层语言运行这句代码时,可分为三部
					 # 1.读取gl_num的值 
					 # 2.进行+1操作
					 # 3.保存结果
	# 程序运行过程中,可能存在,当线程1运行到 2 时,准备运行 3 保存
	# 结果这时线程2,开始抢着运行,这会导致线程1进行了 2(+1操作)却没有运行3(保存),这时gl_num的值还是0
	# 当线程2运行结束,这时线程1会接着运行刚才没有运行的3,这会导致本次循环没有进行+1操作
	# 仅仅只是保存了上次的结果,所以会导致运行结果错误。 



	print("---test1----gl_list = %d" % gl_num)	


def test2(lis):
	global gl_num
	for i in range(lis):
		gl_num += 1
	print("---test1----gl_list = %d" % gl_num)		


def main():

	t1 = threading.Thread(target=test1, args=(1000000,))
	t2 = threading.Thread(target=test2, args=(1000000,))

	t1.start()
	t2.start()
	
	# 等3秒让上面两个线程执行完毕
	time.sleep(3)
	print("---main-----gl_num = %d---" % gl_num)


if __name__ == '__main__':
	main()

yy_10_使用互斥锁解决资源竞争问题

import threading
import time


gl_num = 0

# 创建一个互斥锁,默认是没有上锁的
mutex = threading.Lock()



def test1(lis):
	global gl_num

	# 上锁,如果之前没有上锁,上锁成功
	# 如果上锁之前,已经被上锁,那么此时会堵塞在这里,直到这个锁被解开
	mutex.acquire()
	
	for i in range(lis):
		gl_num += 1
	
	# 解锁 (1000000次循环遍历运行结束才会解锁)
	mutex.release()

	print("---test1----gl_list = %d" % gl_num)	


def test2(lis):
	global gl_num
	# 上锁
	mutex.acquire()

	for i in range(lis):
		gl_num += 1
	# 解锁
	mutex.release()

	print("---test2----gl_list = %d" % gl_num)		


def main():

	t1 = threading.Thread(target=test1, args=(1000000,))
	t2 = threading.Thread(target=test2, args=(1000000,))

	t1.start()
	t2.start()
	
	# 等3秒让上面两个线程执行完毕
	time.sleep(2)
	print("---main-----gl_num = %d---" % gl_num)


if __name__ == '__main__':
	main()


yy_11_使用互斥锁解决资源竞争问题(方法2)

import threading
import time


gl_num = 0

# 创建一个互斥锁,默认是没有上锁的
mutex = threading.Lock()



def test1(lis):
	global gl_num
	
	for i in range(lis):
		
		# 上锁的代码越少越好
		# 上个方法太狠,把锁加在for循环上面,会导致直到这个循环遍历运行完毕才会解锁
		# 问题仅仅是出在了这句代码上,只要让它把底层的3个步骤运行完毕,就可以解锁了
		mutex.acquire()
		
		gl_num += 1
	
		# 解锁
		mutex.release()

	print("---test1----gl_list = %d" % gl_num)	

def test2(lis):
	global gl_num

	for i in range(lis):
		# 上锁
		mutex.acquire()
		
		gl_num += 1
	
		# 解锁
		mutex.release()

	print("---test2----gl_list = %d" % gl_num)		


def main():

	t1 = threading.Thread(target=test1, args=(1000000,))
	t2 = threading.Thread(target=test2, args=(1000000,))

	t1.start()
	t2.start()
	
	# 等3秒让上面两个线程执行完毕
	time.sleep(3)
	print("---main-----gl_num = %d---" % gl_num)


if __name__ == '__main__':
	main()



类里面使用线程的固定方法(把要执行线程的程序写到run方法中就可以了):

import threading
import time

class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            msg = "I'm "+self.name+' @ '+str(i) #name属性中保存的是当前线程的名字
            print(msg)


if __name__ == '__main__':
    t = MyThread()
    t.start()

猜你喜欢

转载自blog.csdn.net/JJandYY135/article/details/83004182