Python线程问题

目录

线程

什么是线程

  • 是系统分配给处理器时间资源的基本单位,或者说进程之内独立执行的一个单元执行流

特点

  • 程序执行的最小单位

为什么需要线程

  1. 进程在同一时段只能做一件事情,如果想做很多事情,就会有些困难
  2. 进程在执行中遭遇阻塞,那么整个进程就会挂起

如何开启线程

#方式一
from threading import Thread
import time

###线程开启的第一种方式
def mythred():
    print('线程开启')
    time.sleep(5)
    print('线程结束')
#线程中可加可不加
if __name__ == '__main__':
    t = Thread(target = mythred)
    t.start()


#####方式二
from threading import Thread
import time
#通过类继承额方法
class Mythred(Thread):
    def run(self):
        print('线程开启')
        time.sleep(5)
        print('线程结束')

t = Mythred()
t.start()

线程创建速度vs进程创建速度

from threading import Thread
from multiprocessing import Process
import time

def task(name):
    print(f'{name} is running')
    time.sleep(2)
    print(f'{name} is end')


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

'''
开启子线程的打印效果:

子线程 is running
主
子线程 is end

开启子进程打印效果:

主
子进程 is running
子进程 is end

进程和线程的创建速度
开启子进程需要申请资源开辟空间 慢
开启子线程只是告诉操作系统一个执行方案 快
'''

线程的join方法

线程的join方法使用起来与进程的join方法相同

from threading import Thread
import time
def task():
    print('子线程 start')
    time.sleep(2)
    print('子线程 end')

t = Thread(target=task)
t.start()
t.join() # 等待子线程运行结束
print('主线程')

守护线程

# 守护线程 守护的是进程的运行周期
from threading import Thread,enumerate,currentThread
import time

def task():
    print('守护线程开始')
    print(currentThread())
    time.sleep(20)
    # print('守护线程结束')

def task2():
    print('子线程 start')
    time.sleep(5)
    print(enumerate())
    print('子线程 end')

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task2)
    t1.daemon = True
    t2.start()
    t1.start()
    print('主')

线程锁的安全问题

from threading import Thread,Lock

x = 0
def task():
    global x
    for i in range(100000):
        x += 1


t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()

print(x)

228891

上述代码我们发现,本应该为300000的x值发生了偏差。

解决方法
from threading import Thread,Lock

x = 0
lock = Lock()
def task():
    global x
    lock.acquire()
    for i in range(200000):
        x += 1
    lock.release()

t1 = Thread(target=task)
t2 = Thread(target=task)
t3 = Thread(target=task)
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print(x)

线程死锁问题

所谓死锁

  • 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
from threading import Thread,Lock
lock1 = Lock()
lock2 = Lock()
import time
class Mythread(Thread):
    def run(self):
        self.task1()
        self.task2()
    def task1(self):
        lock1.acquire()
        print(f'{self.name}抢到了锁一')
        lock2.acquire()
        print(f'{self.name}抢到了锁二')
        lock2.release()
        print(f'{self.name}释放掉了锁二')
        lock1.release()
        print(f'{self.name}释放掉了锁一')

    def task2(self):
        lock2.acquire()
        print(f'{self.name}抢到了锁二')


for i in range(3):
    t = Mythread()
    t.start()

递归锁(用于解决死锁问题)

from threading import Thread,Lock,RLock
# 递归锁 在同一个线程内可以被多次acquire
# 如何释放 内部相当于维护了一个计数器 也就是说同一个线程 acquire了几次就要release几次
mutex1 = RLock()
mutex2 = mutex1
import time
class MyThreada(Thread):
    def run(self):
        self.task1()
        self.task2()
    def task1(self):
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        print(f'{self.name} 释放了 锁1 ')

    def task2(self):
        mutex1.acquire()
        print(f'{self.name} 抢到了 锁1 ')
        mutex1.release()
        print(f'{self.name} 释放了 锁1 ')

for i in range(3):
    t = MyThreada()
    t.start()

信号量

含义:
  • 一个进程向另一个进程发送一个信号来传递某种信息,接收者根据接收到的信号进行相应的行为

使用threading模块里的Semaphore类实现了信号量对象

from threading import Thread,currentThread,Semaphore
import time

def task():
    sm.acquire()
    print(f'{currentThread().name} 在执行')
    time.sleep(3)
    sm.release()

sm = Semaphore(5)
for i in range(15):
    t = Thread(target=task)
    t.start()

原文地址:https://www.cnblogs.com/ledgua/p/11543917.html