上海 day31--线程

目  录

一、线程相关理论

1、什么是线程?

线程是cpu调度的最小单位,能够独立运行。(进程是资源分配的最下单位,线程是CPU调度的最小单位

进程:资源单位

线程:执行单位

如果将内存比作一个工厂的话,那进行就相当于一个车间,线程就是车间里面的流水线!

PS: 每个进程都自带一个线程,线程才是真正的执行单位,进程只是在代码运行过程中提供所需要的资源!

2、为什么需要线程?

开进程
        1.申请内存空间  耗资源
        2."拷贝代码"    耗资源

开线程
        一个进程内可以起多个线程,并且线程与线程之间数据是共享的
ps:开启线程的开销要远远小于开启进程的开销

3、线程与进程之间有什么区别?

1)地址空间和其它资源(如打开文件):
 
  进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。
 
2)通信:
 
  进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。
 
3)调度和切换:
 
  线程上下文切换比进程上下文切换要快得多。
 
4)在多线程操作系统中
 
  进程不是一个可执行的实体。
 

二、创建线程的两种方法

使用模块:

  from threading import thread

创建线程的注意事项:

# 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内

方法一:

from threading import Thread
import time

def run(name):
    print('%s is coming..'%name)
    time.sleep(3)
    print('%s is over'%name)

if __name__ == '__main__':
    t = Thread(target=run,args=('egon',))
    t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程,小到t.start()代码执行完 线程就已经开启了
    print('主。。')
'''
执行结果:
    egon is coming..
    主。。
    egon is over
为什么'egon is coming'子线程先执行,主线程后执行?

'''

方法二:

from threading import Thread
import time

class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print('%s is coming..' % self.name)
        time.sleep(3)
        print('%s is over'%self.name)

# 不需要在 __main__ 下建立
t = MyThread('jason')
t.start()
print('主。。')
'''
执行结果:
    jason is coming..
    主。。
    jason is over
'''

三、线程对象及其方法

使用模块:

  from threading import  Thread, current_thread, active_thread

current_thread  获得当前线程的名字

 active_thread   计算当前存活的进程数

注意:

  线程之间是平等的关系,没有主次之分,我们只是认为的将其区分开!!!!

from threading import Thread,current_thread,active_count
import time

def test(name):
    print('%s is running..'%name)
    print('子线程current_thread',current_thread().name)  # 获得子线程的名字
    time.sleep(2)
    print('%s is ending'%name)

t = Thread(target=test,args=('jason',))
# t = Thread(target=test,args=('jason,'))
t.start()
print('主。。')
print('主线程current_thread',current_thread().name)  # 获得主线程的名字

验证线程的os.getpid()  以及判断线程的存活数

代码如下:

from threading import Thread,current_thread,active_count
import time
import os 

def test(name,i):
    print('%s is running..'%name)

    print('', os.getpid())  # 获取子线程的进程号
    time.sleep(i)
    print('%s is ending'%name)

t1 = Thread(target=test,args=('jason',1))
t2 = Thread(target=test,args=('egon',3))
# t = Thread(target=test,args=('jason,'))
t1.start()
t2.start()
# t2.join()  # 主进程等待子进程运行完毕。。。
# print('主。。',active_count())  # 1个线程
t1.join()  # 主进程等待子进程运行完毕。。。
print('主。。',active_count())  # 2个线程
print('',os.getpid())  # 获取主线程的进程号 —— 得知主线程和子线程的进程号相同,验证同属一个进程
'''
执行结果如下:
jason is running..
子 9980
egon is running..
子 9980
jason is ending
主。。 2
主 9980
egon is ending
'''

四、线程间共享数据

线程间共享数据即多个线程操作同一份数据!

代码验证:

from threading import  Thread

money = 1000
def run():
    global money
    money = 999

t = Thread(target=run)
t.start()
print(money)  # 999  说明主线程和子线程两者共享数据,即操作同一份数据

五、守护线程 ******

from threading import Thread,current_thread
import time

def run(i):
    print(current_thread().name)
    time.sleep(i)
    print('GGGGGG')

t1 = Thread(target=run,args=(1,))
t2= Thread(target=run,args=(3,))
t1.daemon = True   # 设置守护线程!!!!!!
t1.start()
t2.start()
print('主。。')
'''
执行结果:
Thread-1
Thread-2
主。。
GGGGGG
GGGGGG
'''
'''
提出问题:为什么主线程结束了,守护线程还可以执行?

主线程的结束也就意味着进程的结束
主线程必须等待其他非守护线程的结束才能结束
(意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
'''

六、线程互斥锁

代码示例:

from threading import Thread,Lock
import time


n = 100

def task(mutex):
    global  n
    mutex.acquire()
    tmp = n
    time.sleep(0.1)
    n = tmp - 1
    mutex.release()

t_list = []
mutex = Lock()
for i in range(100):
    t = Thread(target=task,args=(mutex,))
    t.start()
    t_list.append(t)
for t in t_list:
    t.join()
print(n)

 代码释义:

我们先开了100个线程,为了达到并发的效果,我们将开启的100个线程添加到列表中,然后在循环列表里的线程为线程加 join方法来确保每个线程都可以执行完毕!!

小例子:

from threading import Thread
from multiprocessing import Process
import time
def foo():
    print(123)
    time.sleep(1)
    print("end123")

def bar():
    print(456)
    time.sleep(3)
    print("end456")

if __name__ == '__main__':
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")

程序执行结果是什么?

原文地址:https://www.cnblogs.com/qinsungui921112/p/11341129.html