python中的线程

阅读目录

线程的理解应该结合进程来对比理解更直接

如果我们操作系统当做一个工厂的话,那么创建一个进程就相当于在这个工厂里面新增了一个车间,车间里面存放了很多资源,而车间要运行起来很显然的标志就是流水线,而这些流水线就是线程,可以说线程是执行代码的最小单位。

而线程和进程两者在使用层面上有很大的相似性,所以开启或者说创建线程的2种方式跟创建进程很相似,区别在于导入的模块和类不一样而已。

一、开启线程方法:

--------------------------------------------------------------------
注:如果你对python感兴趣,我这有个学习Python基地,里面有很多学习资料,感兴趣的+Q群:895817687
--------------------------------------------------------------------

from threading import Thread
import time
def task(name):
    time.sleep(2)
    print('%s has no jj' %name)

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

第二种:

from threading import Thread
import time


class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print("%s is running" % self.name)
        time.sleep(1)
        print("%s is done" % self.name)


t1 = MyThread('Mr hello')
t1.start()
t1.join()
print('zhuzhuzhu')

二、线程之间的数据共享

前面我们学到进程的时候知道进程与进程之间内存空间是相互隔离的,互相无法直接访问到,那么线程之间的共享呢

下面通过一段代码来看看数据直接是否共享:

from threading import Thread
x= 99

def task():
    global x
    x = 66

t1 = Thread(target=task)  # 创建子线程对象
t1.start()  # 向操作系统发送子线程执行请求
t1.join()   # 子线程完毕后才往下走,此时子进程已经执行了x = 66,如果最终打印
# 的是99,则代表子进程无法修改主进程中的x,如果是66则子进程与主进程公共一内存空间,可以修改
print(x)   # 结果为66,证明公用一个内存空间

可以看到,线程之间的数据时具有共享性的,所以就会存在一个隐患,当多个线程同时并发操作同一数据时候或者执行同一代码的时候在某种场景下会导致混乱。

这就是我们后面学到的GIL(global interpreter lock)全局解释器锁的必要性的原因。在这里先提一下。

三、线程的互斥锁:

线程的互斥锁,同理进程的互斥锁,作用也是为了保证数据的安全,何种情况:多线程同时访问操作同一数据时候

先产生锁,再在操作数据的那段代码前后加锁,操作完毕释放锁。实现方法:

from threading import Thread, Lock
import time
import random
import json
mutex = Lock()   # 创建锁


class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        time.sleep(0.5)   #保证多线程同一时间抢锁,睡个0.5秒,等待大部分线程都能运行到此处,开始抢锁
        mutex.acquire()   # 加锁
        with open('info', 'r', encoding='utf-8') as f1:     # 简单模拟抢票过程
            dic = json.load(f1)
            num = dic.get('remain')
            # time.sleep(random.randint(1, 5))
            print('剩余票数:%s' % num)
            if not num:
                print('票已售完,%s购票失败' % self.name)
            else:
                dic['remain'] -= 1
                # time.sleep(random.randint(1, 5))
                with open('info', 'w', encoding='utf-8') as f2:
                    json.dump(dic, f2)
                    print('用户%s购票成功!' % self.name)
        mutex.release()           # 释放锁,这里注意释放位置


user2 = MyThread('egon')
user3 = MyThread('jason')
user1 = MyThread('alex')

user2.start()
user3.start()
user1.start()

user1.join()
user2.join()
user3.join()

print('欢迎欢迎')
### Python线程与进程的区别 在Python中,线程和进程都是用于实现并发编程的重要机制,但两者之间存在显著差异。 #### 线程的特点 线程是操作系统能够进行运算调度的最小单位。多个线程可以在同一个进程中共享内存空间和其他资源,这使得线程间通信变得简单快捷[^1]。然而,由于全局解释器锁(GIL)的存在,在CPython实现下,即使启动了多线程,某些情况下也无法真正并行执行CPU密集型任务[^5]。 #### 进程的特点 相比之下,每个进程拥有独立的地址空间,这意味着不同进程之间的数据隔离较好,安全性更高。但是这也带来了更高的开销——创建新进程的成本远大于创建新线程,并且跨进程的数据交换相对复杂一些[^3]。 ### 使用场景分析 对于I/O密集型的应用来说,比如网络爬虫或文件处理工具,使用多线程往往能获得较好的效果;而对于计算密集型的任务,则更适合采用多进程方案以充分利用多核处理器的能力[^2]。 ### 实现示例 以下是简单的多线程和多进程的例子: #### 多线程实例 ```python import threading def print_numbers(): for i in range(5): print(f'Number {i}') thread = threading.Thread(target=print_numbers) thread.start() thread.join() # 主线程等待子线程完成后再继续往下走 ``` #### 多进程实例 ```python from multiprocessing import Process def print_letters(): for letter in 'ABCDE': print(letter) process = Process(target=print_letters) process.start() process.join() # 父进程等待子进程结束之后再继续运行下面的代码 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值