线程

线程:

在操作系统中,每一个进程都有一个空间,而且每一个空间都有一个线程,进程是资源单位,代码的运行过程指的是线程(即进程运行指开辟空间存放资源,线程运行,cpu运行代码块),进程是线程的容器,一个进程内可以有多个线程,多个线程之间可以达到并发执行,线程是程序中一个单子执行单元,所以在启用上比进程快100

线程----------------->单指代码的执行过程

进程----------------->资源的申请与销毁的过程

开启线程有两种方式,整体跟进程差不多:

多个子线程也都是线程,因为都是主线程下的分支

线程可以不用main因为所有的线程都是共享一个进程下的资源

方案一:函数方案
class MyThread(Thread):
    def run(self):#跟进程一样都有一个函数名run
        print("%s is runnong"%self.name)
        time.sleep(2)
        print("%s is done" %self.name)
if __name__ == '__main__':
    t=MyThread()
    t.start()
    print("")
方法二:自定义类

进程vs线程:

from threading import Thread
from multiprocessing import Process
import os,time

def task():
    print("%s is running" %os.getpid())
    time.sleep(2)
    print("%s is done"%os.getpid())
if __name__ == '__main__':
    t=Thread(target=task)
    t.start()
    # t.join()
    print("主线程",os.getpid())
    #线程中主线程的ID跟子线程的ID一样,先走子线程再走主线程
    """
    打印结果
     15592 is running
     主线程 15592
     15592 is done
    """


def done():
    print("%s is running" %os.getpid())
    time.sleep(2)
    print("%s is done"%os.getpid())
if __name__ == '__main__':
    p=Process(target=done)
    p.start()
    print("主进程",os.getpid())
    #进程中主线程的ID跟子进程的ID不一样,先走主进程再走子进程
    """
    打印结果
    主进程 10004
    7084 is running
    7084 is done

    """

进程与线路共享情况:

from threading import Thread
from multiprocessing import Process
import os
n=100
def work():
    global n
    n=0

if __name__ == '__main__':
    p=Process(target=work)
    p.start()
    p.join()
    print("主进程",n)
    #子进程将n改为0,但仅仅改变了子进程的指,但是父进程的n依然还是100

    t=Thread(target=work)
    t.start()#创造子线程
    t.join()
    print("主线程",n)
    #查看结果为0,因为同一进程内的线程之间共享进程内的数据

1、内存共享or隔离

多个进程内存空间彼此隔离

同一个进程下的多个线程共享,该进程内的数据

2、创建速度

造线程的速度比造进程的速度快

线程比进程开启快的原因在于进程开去需要向操作系统发送信号,而线程不需要像进程那样去向操作系统发送信号,而是可以直接执行

3、主与子ID是否相同

进程中主进程与子进程ID不相同,进程中先走主进程再走子进程

线程中主线程与子线程ID相同,线程中先走子线程,再走主线程

守护线程:

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

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


t1=Thread(target=foo)
t2=Thread(target=bar)

t1.daemon=True
t1.start()
t2.start()
print("main-------")

'''
123
456
main-------
end123
end456

'''

守护线程会在本进程内所有非守护线程都死掉了才跟着死

守护线程其实守护的是整个进程的运行周期(线程内所有的非守护线程都运行完毕)

互斥锁:

from threading import Thread,Lock
import time
x=100
mutex=Lock()
def task():
    global x
    temp=x
    time.sleep(1)#在有等待的地方,如果main下面没有join()会打印出错
    x=temp-1
if __name__ == '__main__':
    t=Thread(target=task)
    t.start()
    t.join()
    print(x)

在线程中,加入时间睡眠后,如果不运用join()就会影响测试结果,因为计算在睡眠的下面,遇到睡眠后会先打印main下面的主线程printx,也就造成了输入为100的打印结果,加上join()后(主线程要等待子线程运行完毕后再运行)得到的值是正确的99

from threading import Thread
import time

x = 100
def task():
    global x
    temp = x
    time.sleep(1)
    temp -= 1
    x=temp
if __name__ == '__main__':
    tlst=[]
    for i in range(100):
        t = Thread(target=task)
        tlst.append(t)
        t.start()
        for i in range(len(tlst)):
            tlst[i].join()
        print(x)

通过放慢的方式可以看出,如果没有join()的情况下直接是显示100,在有join()等待子线程结束完毕之后再运行主线程是正确的显示

from threading import Thread,Lock
import time
x=100
mutex=Lock()
def task():
    time.sleep(0.1)
    global x
    with mutex:
        x -= 1
if __name__ == '__main__':
    for i in range(100):#循环次数
        t = Thread(target=task)
        t.start()
        t.join()
        print(x)
加互斥锁版本
from threading import Thread,current_thread,active_count,enumerate
import time
def task():
    print("%s 子线程原名" %current_thread().name)
    time.sleep(1)
    print("%s 子线程修改过后名字" %current_thread().name)
if __name__ == '__main__':
    t=Thread(target=task)
    t.start()
    t.join()
    # print("判断线程是否存活",t.is_alive())
    # print("显示主线程名字",current_thread().getName())
    # print(t.name)#看当前线程的名字
    # print("显示存活的线程数",active_count())
    # print("将所有线程放入列表",enumerate())
    # current_thread().setName("主线程")#修改主线程名字
    # print("parent",current_thread().name),"我原名MainThread,现名主线程")
了解点:
from threading import Thread,Lock,active_count
import time
mutexA = Lock()
mutexB = Lock()
class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
    def f1(self):
        mutexA.acquire()
        print("A")
        mutexB.acquire()
        print("B")
        mutexB.release()
        mutexA.release()
    def f2(self):
        mutexB.acquire()
        print("A")
        time.sleep(1)
        mutexA.acquire()
        print("B")
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(10):
        t = MyThread()
        t.start()
    print(active_count())
死锁现象和递归锁
from threading import Thread, active_count, RLock
import time
obj = RLock()
mutexA = obj
mutexB = obj
class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()
    def f1(self):
        mutexA.acquire()
        print("A")
        mutexB.acquire()
        print("B")
        mutexB.release()
        mutexA.release()
    def f2(self):
        mutexB.acquire()
        print("A")
        time.sleep(1)
        mutexA.acquire()
        print("B")
        mutexA.release()
        mutexB.release()
if __name__ == '__main__':
    for i in range(10):
        t = MyThread()
        t.start()
    print(active_count())

信号量

控制同一时间互斥锁的量,并且有人释放锁会有人马上拿到锁

from threading import Thread, Semaphore, current_thread
import time
import random
sm = Semaphore(5)
def task():
    with sm:
        print("%s正在卫生间" % current_thread().name)
    time.sleep(random.random())
if __name__ == '__main__':
    for i in range(20):
        t = Thread(target=task)
        t.start()
原文地址:https://www.cnblogs.com/yf18767106368/p/9306763.html