资讯专栏INFORMATION COLUMN

python之线程锁

junnplus / 2423人阅读

摘要:信号量使用前执行后发现不断在输出使用后通过执行上面的代码,我们发现一次只能输出三个数字,控制访问并发量事件等待后,才能往下执行定义五个线程重置,使得起到阻塞作用启动所有线程等待唤醒所有线程等待唤醒所有线程

本文讲python中的四种锁
Lock互斥锁
使用前

num = 0


def a():
    global num
    for _ in range(10000000):
        num += 1


def b():
    global num
    for _ in range(10000000):
        num += 1


if __name__ == "__main__":
    t1=Thread(target=a)
    t1.start()
    t2=Thread(target=b)
    t2.start()
    t1.join()
    t2.join()
    print(num)    #基本永远会小于20000000

使用后

num = 0


def a(lock):
    global num
    for _ in range(1000000):
        with lock:
            num += 1


def b(lock):
    global num
    for _ in range(1000000):
        with lock:
            num += 1


if __name__ == "__main__":
    lock = threading.Lock()
    t1=Thread(target=a, args=(lock,))
    t1.start()
    t2=Thread(target=b, args=(lock,))
    t2.start()
    t1.join()
    t2.join()
    print(num)    #永远会输出20000000

RLock重用锁

#在之前的代码中永远不可能出现锁在没释放之前重新获得锁,但rlock可以做到,但只能发生在一个线程中,如:
num = 0


def a(lock):
    with lock:
        print("我是A")
        b(lock)


def b(lock):
    with lock:
        print("我是b")

if __name__ == "__main__":
    lock = threading.Lock()
    t1 = Thread(target=a, args=(lock,))
    t1.start()    #会发生死锁,因为在第一次还没释放锁后,b就准备上锁,并阻止a释放锁

使用后

if __name__ == "__main__":
    lock = threading.RLock()    #只需要改变锁为RLock程序马上恢复
    t1 = Thread(target=a, args=(lock,))
    t1.start()

Condition同步锁

#这个程序我们模拟甲乙对话
Jlist = ["在吗", "干啥呢", "去玩儿不", "好吧"]
Ylist = ["在呀", "玩儿手机", "不去"]


def J(list):
    for i in list:
        print(i)
        time.sleep(0.1)


def Y(list):
    for i in list:
        print(i)
        time.sleep(0.1)


if __name__ == "__main__":
    t1 = Thread(target=J, args=(Jlist,))
    t1.start()
    t1.join()
    t2 = Thread(target=Y, args=(Ylist,))
    t2.start()
    t2.join()    #上面的程序输出后发现效果就是咱们想要的,但是我们每次输出后都要等待0.1秒,也无法正好确定可以拿到时间片的最短时间值,并且不能保证每次正好都是另一个线程执行。因此,我们用以下方式,完美解决这些问题。

使用后

Jlist = ["在吗", "干啥呢", "去玩儿不", "好吧"]
Ylist = ["在呀", "玩儿手机", "不去","哦"]


def J(cond, list):
    for i in list:
        with cond:
            print(i)
            cond.notify()
            cond.wait()


def Y(cond, list):
    for i in list:
        with cond:
            cond.wait()
            print(i)
            cond.notify()


if __name__ == "__main__":
    cond = threading.Condition()
    t1 = Thread(target=J, args=(cond, Jlist))
    t2 = Thread(target=Y, args=(cond, Ylist))
    t2.start()
    t1.start()    #一定保证t1启动在t2之后,因为notify发送的信号要被t2接受到,如果t1先启动,会发生阻塞。

Seamplore信号量
使用前

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

    def run(self):
        time.sleep(1)
        print(self.name)


class A(threading.Thread):
    def __init__(self):
        super().__init__()

    def run(self):
        for i in range(100):
            b = B(i)
            b.start()


if __name__ == "__main__":
    a = A()
    a.start()    #执行后发现不断在输出

使用后

class B(threading.Thread):
    def __init__(self, name, sem):
        super().__init__()
        self.name = name
        self.sem = sem

    def run(self):
        time.sleep(1)
        print(self.name)
        sem.release()


class A(threading.Thread):
    def __init__(self, sem):
        super().__init__()
        self.sem = sem

    def run(self):
        for i in range(100):
            self.sem.acquire()
            b = B(i, self.sem)
            b.start()


if __name__ == "__main__":
    sem = threading.Semaphore(value=3)
    a = A(sem)
    a.start()    #通过执行上面的代码,我们发现一次只能输出三个数字,sem控制访问并发量

Event事件

import time
import threading


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

    def run(self):
        print("Thread: {} start at {}".format(self.name, time.ctime(time.time())))
        # 等待event.set()后,才能往下执行
        self.event.wait()
        print("Thread: {} finish at {}".format(self.name, time.ctime(time.time())))


event = threading.Event()

# 定义五个线程
threads = [MyThread(str(i), event) for i in range(1,5)]

# 重置event,使得event.wait()起到阻塞作用
event.clear()

# 启动所有线程
[t.start() for t in threads]

print("等待5s...")
time.sleep(5)

print("唤醒所有线程...")
event.set()

# output:
"""
Thread: 1 start at Sun May 13 20:38:08 2018
Thread: 2 start at Sun May 13 20:38:08 2018
Thread: 3 start at Sun May 13 20:38:08 2018
Thread: 4 start at Sun May 13 20:38:08 2018

等待5s...

唤醒所有线程...
Thread: 1 finish at Sun May 13 20:38:13 2018
Thread: 4 finish at Sun May 13 20:38:13 2018
Thread: 2 finish at Sun May 13 20:38:13 2018
Thread: 3 finish at Sun May 13 20:38:13 2018
"""

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/42783.html

相关文章

  • 通读Python官方文档Threading

    摘要:但现在线程没有优先级,没有线程组,不能被销毁停止暂停开始和打断。守护线程也会结束,并强行终止整个程序。在中,他是目前可用的最底层的同步原语,由模块提供。当处于状态时,方法可以将状态变为,并立即返回。否则会抛出错误。对象实现某些服务的共进退。 Python的threading模块松散地基于Java的threading模块。但现在线程没有优先级,没有线程组,不能被销毁、停止、暂停、开始和打...

    jasperyang 评论0 收藏0
  • python模块threading

    摘要:的类行为是的类行为的子集,目前尚不支持优先级线程组,线程无法销毁停止暂停恢复或中断。表示继承创建该线程的当前线程的属性。重入锁,同步原语的一种,可由同一线程多次获取已持有的锁。 threading在低级的_thread模块上构建了更高级的线程接口。 threading模块基于Java线程模型设计。不过Java中锁和条件变量是每个对象的基本行为,在python中却是单独的对象。pytho...

    nanchen2251 评论0 收藏0
  • Python系统编程线程

    摘要:可以将它们认为是在一个主进程或主线程中并行运行的一些迷你进程。因此与进程相比,线程之间的信息共享和通信更加容易。当上锁的线程执行完毕进行解锁,堵塞的线程就争夺到上锁权而进行代码块的运行。 threading模块 线程简述 线程(轻量级进程)与进程类似,不过它们是在同一个进程下执行的,并共享相同的上下文。可以将它们认为是在一个主进程或主线程中并行运行的一些迷你进程。 线程包括开始、执行顺...

    XboxYan 评论0 收藏0
  • python并发4:使用thread处理并发

    摘要:如果某线程并未使用很多操作,它会在自己的时间片内一直占用处理器和。在中使用线程在和等大多数类系统上运行时,支持多线程编程。守护线程另一个避免使用模块的原因是,它不支持守护线程。 这一篇是Python并发的第四篇,主要介绍进程和线程的定义,Python线程和全局解释器锁以及Python如何使用thread模块处理并发 引言&动机 考虑一下这个场景,我们有10000条数据需要处理,处理每条...

    joywek 评论0 收藏0
  • 操作系统实战

    摘要:操作系统实战临界资源保护临界资源进行通信线程间同步互斥量和读写锁自旋锁条件变量进程间同步共享内存域套接字重要概念用户态与内核态上下文切换协程线程同步之互斥量互斥量锁可以保证多线程的指令按顺序执行,避免两个线程的指令交叉执行即原子性原子性是指 操作系统实战 临界资源 保护临界资源/进行通信 线程间同步 互斥量和 读写锁 自旋锁 条件变量 进程间同步 共享内存 域套接字 重要概念 用...

    developerworks 评论0 收藏0

发表评论

0条评论

junnplus

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<