线程

概念

  • 线程又被称之为轻量级进程
  • 一个进程可拥有多个并行的线程
  • 通俗的一点说就是一个程序有多个任务可以同时进行
  • 一个进程中线程共享相同的内存单元/内存地址空间,可以访问相同的成员
  • 他们从同一个堆中分配对象,通讯、数据交换,同步操作
  • 由于线程间的通信是在同一地址空间进行的,所以,不需要额外的通讯机制
  • 通过以上等优势来提高Python的速度

进程与线程的区别

  • 进程是系统进行资源分配和调度的独立单位
  • 进程在执行过程中拥有独立的内存单元,多个线程共享,从而提高效率
  • 线程是一个进程的实体,是CPU调度和分配的基本单位,从而提高程序运行效率
  • 线程基本不拥有系统资源,只拥有运行时的一点必不可少的资源,但他与其他线程共享进程中的所有资源
  • 使用多线程程序并发比较高
  • 线程不能独立执行,必须依赖进程
  • 线程执行开销小,但是不利于资源的管理保护

涉及到的模块

  • from threading import Thread
  • import time

创建线程

引入模块

1.import time
2.from threading import Thread

创建线程

1.创建一个执行函数
2.判断是否主动执行
3.创建单个进程或者循环创建出多个线程
4.线程开始执行
5.实例1:

// An highlighted block
from threading import Thread

import time

def xc():
    print("当前线程执行了")


if __name__ == '__main__':
    for i in range(5):
        time.sleep(i)
        t = Thread(target=xc)
        t.start()

6.实例2:

// An highlighted block
from threading import Thread

import time

def xc(num):
   print("当前线程执行了%d"%num)


if __name__ == '__main__':
   for i in range(5):
       time.sleep(i)
       t = Thread(target=xc,args=(i+1,))
       t.start()

7.实例3:

// An highlighted block
from threading import Thread

import time

def sing():
   for i in range(3):
       print("我正在唱歌")


t = Thread(target=sing)
t.start()

线程子类化

  • 将线程封装到一个类中
  • 对数据进行封装
  • 实例1:
// An highlighted block
from threading import Thread

import time

class MyThread(Thread):
   def run(self):
       for i in range(10):
           time.sleep(2)
           string = "My name is "+self.name+" @ "+str(i)
           print(string)

m = MyThread()

m.start()

  • 实例2:
// An highlighted block
from threading import Thread

import time

class MyThread(Thread):
    def run(self):
        for i in range(10):
            time.sleep(2)
            string = "my name is "+self.name+" @ "+str(i)
            print(string)

for i in range(2):
    t = MyThread()
    t.start()

线程的状态

  • 阻塞 : 多线程的顺序是不规律的,当执行到sleep语句的时候,线程将被阻塞
  • 就绪 : 当sleep语句结束后,程序将要执行,这时线程处在就绪的状态,等待调度,而线程调度会自行选择一个线程执行
  • 运行 : 调度处线程之后,程序执行,这个状态就是运行状态
  • 运行时可能会出现阻塞事件

全局变量

概念

  • 在一个进程内,所有线程共享全局变量
  • 能够在其他地方都不实用的环境中完成线程间的数据共享
  • 缺点 : 线程可以对全局变量随意篡改,可能造成多线程间的全局变量混乱

共享

  • 在线程的操作中,全局变量在线程中是共享的
    实例1:
// An highlighted block
from threading import Thread

import time

g_num = 100

def worker1():
    global g_num
    for i in range(3):
        #重新定义了g_num  所以g_num如果不声明为全局变量  他就是局部变量
        g_num += 1
        print("worker1里面的g_num等于%d"%g_num)

def worker2():
    print("worker2里面的g_num等于%d"%g_num)

print("主线程的g_num等于%d"%g_num)

t1 = Thread(target=worker1)
t1.start()

time.sleep(2)
print('')

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

实例2(反例,传参):

// An highlighted block
from threading import Thread

import time

g_num = 100

def worker1(num):
    for i in range(3):
        num += 1
        print("worker1里面的g_num等于%d"%num)

def worker2(num):
    print("worker2里面的g_num等于%d"%num)

print("主线程的g_num等于%d"%g_num)

t1 = Thread(target=worker1,args=(g_num,))
t1.start()

time.sleep(2)
print('')

t2 = Thread(target=worker2,args=(g_num,))
t2.start()

这个以传参的形式赋值,那么就不属于全局变量,结果不共享

线程同步

概念

  • 当多线程同时修改某一个数据的时候,需要进行同步控制
  • 线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁
  • 互斥锁保证每次只有一个线程进行写入操作,从而保证多线程的情况下数据的正确性
  • 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改,直到该线程释放资源,将资源的状态变成“非锁定”,其他线程才能再次锁定该资源
  • threading模块中定义了Lock类,可以方便的处理锁定

需要引入的模块

  • from threading import Thread
  • from threading import Lock
  • import time

同步控制

  • 案例:
// An highlighted block
from threading import Thread

num = 0
def worker():
    global num
    for i in range(2000000):
        num += 1

if __name__ == '__main__':
    for x in range(2):
        t = Thread(target=worker)
        t.start()

print("这是线程的结果=======%d"%num)

多次变更,在两万六千次左右就会出现误差

  • 原因:数据进行运算时,先从内存中读到寄存器中去,运算完毕后,再从寄存器中读取到内存中来。
  • 创建锁 : mutex = threading.Lock()
  • 锁定 : mutex.acquire([blocking])
    1.如果设定blocking为True,则当前线程会阻塞,知道获取这个锁为止,如果没有设定,默认为True
    2.如果设定blocking为False,则当前线程不会阻塞
  • 释放 : mutex.release()
  • 实例:
// An highlighted block
from threading import Thread,Lock

import time

num = 0
#创建互斥所
mutex = Lock()
def worker():
   global num
   for i in range(10000000):
       mutexPlag = mutex.acquire(False)
       if mutexPlag:
           num += 1
           mutex.release()

if __name__ == '__main__':
   for i in range(2):
       t = Thread(target=worker)
       t.start()
       t.join()
   print(num)

  • 死锁现象 : 如果将线程锁定,而没有释放,那么就会出现死锁现象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值