线程与其他锁

什么是线程

进程 : 资源分配的最小单位,可以利用多核,操作系统调度,数据不安全,开启关闭切换时间开销大

线程 :能被操作系统调度(给CPU执行)的最小单位.

打开一个程序就会产生进程 开启空间,加载数据. 进程 之间 数据隔离,是 资源分配的最小单位,

进程之内 会产生线程: 主要任务:执行代码. 数据互通

线程是依赖于进程, 一个进程可以包含多个线程.但是一定有一个主线程. 线程才是cpu执行的最小单元.

线程vs进程(理论)

  1. 开启多进程开销非常大. 10~100.开启线程开销非常小.
  2. 开启多进程的速度慢,开启多线程速度快.
  3. 进程之间数据不能直接共享通过队列可以.同一个进程下的线程之间的数据可以共享

线程创建2种方式

与创建 进程差不了多少

# 第一种方式 Thread父来的  线程
# from threading import Thread
# def task(name):
#     print(f'{name} is running')
# if __name__ == '__main__':
#     t = Thread(target=task,args=('mcsaoQ',))
#     t.start()
#     print('主线程')


from threading import Thread
class MyThread(Thread):

    def run(self):
        print(f'{self.name} is running')
if __name__ == '__main__':
    t = MyThread()
    t.start()

    print('主线程')

线程与速度对比.

线程绝对要比进程要快:

先有进程才有线程 线程是cpu调度的最小单位 线程不用开空间

pid

在同一进程下 不同线程下 os.getpid()都是本线程的pid

# pid 进程号
from threading import Thread
import os

def task():
    print(f'子线程: {os.getpid()}')

if __name__ == '__main__':
    t = Thread(target=task,)
    t.start()
    print(f'主线程: {os.getpid()}')

线程之间共享资源

在同一进程下 数据是共享的

# from threading import Thread
# x = 1000
# def task():
#     global x
#     x = 0
# if __name__ == '__main__':
#     t = Thread(target=task)
#     t.start()
#     # t.join()
#     print(f'主线程: {x}')

线程的其他方法

# threading模块的方法:
#     # print(threading.current_thread().name)  # MainThread name 是当前线程的名字, 
print(threading.current_thread().ident) 是当前线程的id
#     # print(threading.enumerate())  # 返回一个列表 放置的是所有的线程对象 
#     print(threading.active_count())  # 获取活跃的线程的数量(包括主线程)



# from threading import Thread
# import threading
# import time
# def task(name):
#     time.sleep(1)
#     print(f'{name} is running')
#     print(threading.current_thread().name)
#
# if __name__ == '__main__':
#     for i in range(5):
#         t = Thread(target=task,args=('mcsaoQ',))
#         t.start()
#     # 线程对象的方法:
#     # time.sleep(1)
#     # print(t.is_alive())  # 判断子线程是否存活  ***
#     # print(t.getName())  # 获取线程名
#     # t.setName('线程111')
#     # print(t.getName())  # 获取线程名

多线程中的守护线程

# 主线程什么时候结束???
# 多线程是同一个空间,同一个进程,进程代表 空间,资源. 静态的.
# 主线程是进程空间存活在内存中的必要条件.
# 主线程: 必须要等待所有的子线程全部结束之后,你在执行完毕,进程在消失.
# 守护线程必须等待主线程结束才结束, 主线程必须等待所有的非守护线程结束才能结束.


推算出
# 守护线程: 必须等待所有的非守护线程 以及 主线程结束之后才能够结束.

互斥锁(锁)

# 互斥锁与join区别?
# 互斥锁 随机抢锁,公平. join 提前排好顺序,不公平.但是都是串行.

# from threading import Thread
# import time
# x = 100
#
# def task():
#     global x
#     temp = x
#     time.sleep(1)
#     temp -= 1
#     x = temp
#
# if __name__ == '__main__':
#     t = Thread(target=task)
#     t.start()
#     t.join()
#     print(f'主线程{x}')


没加锁
from threading import Thread
import time
x = 100

def task():
    global x
    temp = x
    time.sleep(1)
    temp -= 1
    x = temp

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

    for i in t_l:
        i.join()

    print(f'主线程{x}')

加了锁 并发
from threading import Thread
from threading import Lock
x = 100

def task(lock):
    global x
    lock.acquire()
    temp = x
    # time.sleep(0.1)
    temp -= 1  # 99
    x = temp  # 99
    lock.release()

if __name__ == '__main__':
    lock = Lock()
    t_l = []
    for i in range(100):
        t = Thread(target=task,args=(lock,))
        t_l.append(t)
        t.start()
    for i in t_l:
        i.join()
    print(f'主线程{x}')

死锁现象,

第一种 加了2次同样的锁

第2种 2个进程都想获取对方的锁 却不可能实现

可重复锁Rlock

可重复锁,是线程相关的锁

不管实列化多少次都是同一只把锁,

引用计数,只要计数不为0,其他线程不可以抢.

from threading import Thread
from threading import RLock
import time

lock_A = lock_B = RLock()

class MyThread(Thread):


    def run(self):

        self.f1()
        self.f2()

    def f1(self):

        lock_A.acquire()
        print(f'{self.name}拿到 A锁')

        lock_B.acquire()  # 第二个线程抢B锁
        print(f'{self.name}拿到 B锁')
        lock_B.release()

        lock_A.release()

    def f2(self):

        lock_B.acquire()
        print(f'{self.name}拿到 B锁')

        time.sleep(1)  # 第一个线程 睡1秒
        lock_A.acquire()  # 第一个线程抢A锁
        print(f'{self.name}拿到 A锁')
        lock_A.release()

        lock_B.release()


if __name__ == '__main__':
    # for i in range(3):
    #     t = MyThread()
    #     t.start()
    t1 = MyThread()
    t1.start()
    t2 = MyThread()
    t2.start()
    t3 = MyThread()
    t3.start()
    print('主线程')

信号量

本质就是一个计数器,用来为多个进程共享的数据结构提供受控访问。

from threading import Semaphore
也是一把锁
# 之前讲的锁都是只允许一个线程或者进程进入.
# 信号量允许多个线程或者进程同时进入

from threading import current_thread
from threading import Semaphore
import time
import random
sm = Semaphore(4)#控制进入个数
def go_public_wc():
    sm.acquire()
    print(f'{current_thread().name}进入了')
    time.sleep(random.randint(1, 3))
    sm.release()


if __name__ == '__main__':

    for i in range(20):
        t = Thread(target=go_public_wc)
        t.start()

面试题

进程:正在执行的程序文件,它是资源单位
线程:cpu调度的最小单元,执行单位
多进程:同-时刻开启多个进程并发(并行)的执行.
多线程:同一时刻开启多个线程并发(并行)的执行.
守护线程:设置一个子线程为守护线程,它会等待所有的非守护线程以及主线程结束之后,在结束.
死锁现象?
多个线程(进程)竞争资源如果开启的互斥锁过多会遇到互相抢锁,等待的情况程序夯住.
同时给一个线程(进程)连续加锁多次.
利用递归锁解决死锁现象.
什么递归锁: Rlock锁上有引用计数每次引用计数+ 1,释放时计数-1,只要计数不为0,其余线程或者进
程都不可以引用此锁.
信号量:同一时刻允许多个线程(进程)开启任务. 

转载于:https://www.cnblogs.com/saoqiang/p/11377412.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值