学习总结(三十四)

浪子不回头ぞ 提交于 2020-04-06 11:31:04

1.线程

    什么是线程

            线程是操作系统最小的运算调度单位,被包含在进程中,一个线程就是一个固定的执行流程

2.线程与进程的关系

         线程不能单独存在必须存在于进程中,进程是一个资源单位,其包含了运行程序所需的所有资源,线程才是真正的执行单位

    没有线程,进程中的资源无法被利用起来,所以一个进程至少包含一个线程,称之为主线程,当我们启动一程序时,操作系统就会为自己这个程序创建一个主线程,线程可以由程序后期开启,自己开启线程称之为子线程

3.为什么需要线程

               目的只有一个就是提高效率

4.多线程的使用方式

     继承Thread类,然后重写run()方法

from threading import Thread,current_thread
import time

def task():
    print("2",current_thread())
    print("子进程running")
    time.sleep(10)
    print("子进程")

if __name__ == '__main__':
    t=Thread(target=task)
    t.start()
    print("主线程")
    print("1",current_thread())

class myThread(Thread):
    def run(self):
          print("子进程tun")
m=myThread()
print("父进程")

 

5.线程的特点

       1)创建开销小

       2)同一个进程中的多个线程数据可以共享

       3)多线程之间,是平等关系,没有父子关系,所有的线程的PID都是相同的

  

# 创建线程开销对比
import os
from threading import  Thread
from multiprocessing import Process

import time


def task():
    # print("hello")
    print(os.getpid())
    pass

if __name__ == '__main__':

    st_time = time.time()

    ts = []
    for i in range(100):
        t = Thread(target=task)
        # t = Process(target=task)
        t.start()
        ts.append(t)

    for t in ts:
        t.join()

    print(time.time()-st_time)
    print("主over")

  

6.守护线程

           一个线程可以设置为另一个线程的守护线程

          特点: 被守护线程结束后守护线程也随之结束

from threading import Thread
import time

def task():
    print("子1running......")
    time.sleep(100)
    print("子1over......")

def task2():
    print("子2running......")
    time.sleep(4)
    print("子2over......")
    
t = Thread(target=task)
t.daemon = True
t.start()

t2 =Thread(target=task2)
t2.start()

print("主over")

  

7.线程 互斥锁

      共享意味着竞争

       线程中也存在安全问题,

       多线程可以并发执行,一旦并发了并且访问了同一个资源就会有问题

       解决方案:还是互斥锁

from threading import Thread,enumerate,Lock
import time

number = 10

lock = Lock()

def task():
    global number
    lock.acquire()
    a = number
    time.sleep(0.1)
    number = a - 1
    lock.release()

for i in range(10):
    t = Thread(target=task)
    t.start()

for t in enumerate()[1:]:
    # print(t)
    t.join()
    
print(number)

8.死锁问题

from threading import Lock, current_thread, Thread

"""
    死锁问题
    当程序出现了不止一把锁,分别被不同的线程持有, 有一个资源 要想使用必须同时具备两把锁
    这时候程序就会进程无限卡死状态 ,这就称之为死锁
    例如:
        要吃饭 必须具备盘子和筷子   但是一个人拿着盘子 等筷子  另一个人拿着筷子等盘子
    
    如何避免死锁问题  
        锁不要有多个,一个足够
        如果真的发生了死锁问题,必须迫使一方先交出锁
        
"""
import time
# 盘子
lock1 = Lock()

# 筷子
lock2 = Lock()

def eat1():
    lock1.acquire()
    print("%s抢到了盘子" % current_thread().name)
    time.sleep(0.5)
    lock2.acquire()
    print("%s抢到了筷子" % current_thread().name)

    print("%s开吃了!" % current_thread().name)
    lock2.release()
    print("%s放下筷子" % current_thread().name)

    lock1.release()
    print("%s放下盘子" % current_thread().name)


def eat2():
    lock2.acquire()
    print("%s抢到了筷子" % current_thread().name)

    lock1.acquire()
    print("%s抢到了盘子" % current_thread().name)


    print("%s开吃了!" % current_thread().name)


    lock1.release()
    print("%s放下盘子" % current_thread().name)
    lock2.release()
    print("%s放下筷子" % current_thread().name)


t1 = Thread(target=eat1)


t2 = Thread(target=eat2)

t1.start()
t2.start()

  

9.可重入锁

       Rlock 称之为递归锁或者可重入锁

      Rlock不是用来解决死锁问题的

           与Lock唯一的区别: Rlock同一线程可以多次执行acquire 但是执行几次acquire就应该对应release几次 如果一个线程

          已经执行过acquire ,其他线程将无法执行acquire

from threading import RLock, Lock, Thread

# l = Lock()
#
# l.acquire()
# print("1")
# l.acquire()
# print("2")


l = RLock()

# l.acquire()
# print("1")
# l.acquire()
# print("2")

def task():
    l.acquire()
    print("子run......")
    l.release()


# 主线程锁了一次
l.acquire()
l.acquire()

l.release()
l.release()
t1 = Thread(target=task)
t1.start()

  

10.信号量

"""
 信号量 了解
Lock  RLock

可以现在被锁定的代码 同时可以被多少线程并发访问
Lock 锁住一个马桶  同时只能有一个
Semaphore 锁住一个公共厕所    同时可以来一堆人


用途: 仅用于控制并发访问   并不能防止并发修改造成的问题
"""

from threading import Semaphore, Thread
import time

s = Semaphore(5)
def task():
    s.acquire()
    print("子run")
    time.sleep(3)
    print("子over")
    s.release()

for i in range(10):
    t = Thread(target=task)
    t.start()

  

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!