线程理论和实操

1.什么是线程

进程其实不是一个执行单位. 进程是一个资源单位
每个进程内自带一个线程. 线程才是cpu上的执行单位

如果把操作系统比喻一座工厂
    在工厂中每造出一个车间 -> 启动一个进程
    每个车间至少有一条流水线 -> 每个进程至少有一个线程

线程 -> 单指代码的执行过程
进程 -> 资源的申请与销毁的过程

2.进程vs线程

1. 内存共享or隔离
    多个进程内存空间彼此隔离
    同一进程下的多个线程共享该进程内的数据
2. 创造速度
    创建线程的速度要远远快与造进程

3.创建线程的两种方式

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 8:44
# @author: Maxs_hu
from threading import Thread
import time


# 方式1:
def task(name):
    print('%s is running' % name)
    time.sleep(2)
    print('done')


if __name__ == '__main__':
    t = Thread(target=task, args=('maxs_hu', ))
    t.start()

    print('主')  # 线程创建速度很快.
"""
maxs_hu is running
主
done
"""


# 方式2:
class Mythreading(Thread):
    def run(self):
        print('%s is running' % self.name)
        time.sleep(3)
        print('%s is done' % self.name)


if __name__ == '__main__':
    t = Mythreading()
    t.start()
    print('main')

4.线程vs进程代码实现

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 8:53
# @author: Maxs_hu
from threading import Thread
from multiprocessing import Process


# 线程的速度快于进程
def task(name):
    print(f'{name} is running')


if __name__ == '__main__':
    t = Thread(target=task, args=('子线程', ))
    p = Process(target=task, args=('子进程', ))
    p.start()

    t.start()
    print('main')


# 同一进程内的线程共享线程内的资源
x = 100

def task():
    global x
    x = 1


if __name__ == '__main__':
    t = Thread(target=task)
    t.start()
    t.join()  # 等待线程执行完毕
    print(x)  # x的值被子线程修改


# 查看pid
import os


def task():
    print('pid: %s' % os.getpid())


if __name__ == '__main__':
    t = Thread(target=task)
    t.start()

    print('主线程: %s' % os.getpid())
    # pid: 5232主线程: 5232

5.守护线程

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 9:09
# @author: Maxs_hu
from threading import Thread, current_thread
import time


# 守护进程会在本进程内的非守护进程的死掉之后跟着死掉
# 守护线程其实守护的是整个进程的运行周期
# def task():
#     print('%s is running' % current_thread().name)
#     time.sleep(2)
#     print('%s is done' % current_thread().name)  # 如果主线程在这条之前运行完了. 就不回输出
#
#
# if __name__ == '__main__':
#     t = Thread(target=task)
#     t.daemon = True  # 设置守护线程
#     t.start()
#     print('main')


# 小案例
def foo():
    print(123)
    time.sleep(3)
    print("end123")  # 这个没有输出


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


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

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

6.守护线程

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 9:24
# @author: Maxs_hu


# 什么是互斥锁:
#   将多个并发任务对共享数据的修改变成串行, 以保证数据安全
#   加上锁之后效率变低. 保证数据安全
from threading import Thread, Lock
import time
x = 100


# def task():
#     global x
#     temp = x
#     time.sleep(0.1)  # 线程全部拿到temp = 100到这里睡了0.1秒. 后面修改数据就都是99. 不符合正常逻辑.
#     x = temp - 1
#
#
# if __name__ == '__main__':
#     t_ls = []
#     for i in range(100):
#         t = Thread(target=task)
#         t_ls.append(t)
#         t.start()
#
#     for t in t_ls:  # 等待子线程运行完毕
#         t.join()
#
#     print(x)


mutex = Lock()


def task():
    global x
    mutex.acquire()
    temp = x
    time.sleep(0.1)  # 线程全部拿到temp = 100到这里睡了0.1秒. 后面修改数据就都是99. 不符合正常逻辑.
    x = temp - 1
    mutex.release()


if __name__ == '__main__':
    t_ls = []
    start_time = time.time()
    for i in range(100):
        t = Thread(target=task)
        t_ls.append(t)
        t.start()

    for t in t_ls:  # 等待子线程运行完毕
        t.join()

    print(x, time.time()-start_time)

7.死锁现象和递归锁

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 10:19
# @author: Maxs_hu
"""
什么是死锁现象:
    相当于两个人拿着对方家里的钥匙. 被锁门里面了
    互相等着拿对方的锁的现象
怎么解决死锁现象:
    递归锁: Rlock原理
        给不同的锁赋值obj递归锁对象. 被赋值的锁被acquire多次. 就会在整体标记多次. 只要存在标记. 后面的线程就只能等着
        而只有release消除所有的标记次数. 才能开始抢锁. 从而解决死锁现象

    递归锁的特点:可以连续的acquire
"""


from threading import Thread, Lock, active_count, RLock
import time

# mutexA=Lock()
# mutexB=Lock()
obj = RLock()  # 递归锁的特点:可以连续的acquire
mutexA = obj
mutexB = obj


class Mythread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        print('%s 拿到A锁' % self.name)

        mutexB.acquire()
        print('%s 拿到B锁' % self.name)
        mutexB.release()

        mutexA.release()

    def f2(self):
        mutexB.acquire()
        print('%s 拿到B锁' % self.name)
        time.sleep(1)

        mutexA.acquire()
        print('%s 拿到A锁' % self.name)
        mutexA.release()

        mutexB.release()


if __name__ == '__main__':
    for i in range(10):
        t = Mythread()
        t.start()
    # print(active_count())

8.信号量

# -*- encoding:utf-8 -*-
# @time: 2022/8/7 10:44
# @author: Maxs_hu


# 信号量: 同一时刻并发执行的任务数
import time
import random
from threading import Thread, current_thread, Semaphore

mutex = Semaphore(5)  # 设置同时并发量为5


def task():
    with mutex:
        print('%s 在上厕所' % current_thread().name)
        time.sleep(random.randint(1, 3))


if __name__ == '__main__':
    for i in range(20):
        t = Thread(target=task)
        t.start()

posted on 2022-08-07 11:02  huxiaofeng  阅读(155)  评论(0编辑  收藏  举报

导航