聊聊并发与锁

283 篇文章 6 订阅
149 篇文章 0 订阅

1.并发与并行

并发可以充分地利用 CPU 资源,一般都会使用多线程实现。多线程的作用是提高任务的平均执行速度,但是会导致程序可理解性变差,编程难度加大。

关于对并发与并行的概念,大家可能一直比较混淆。

  1. 定义:并发指的是多个任务在同一时刻正在进行,但实际上只有一个任务在一段时间内被处理;并行指的是多个任务在同一时刻同时被处理。

  2. 时间:并发涉及的是任务的同时发生;并行涉及的是任务的同时处理。

  3. 实现:并发可以通过多线程实现,每个线程分别执行不同的任务;并行则需要多核处理器才能实现,多核处理器可以同时处理多个任务。

也可以通过举例说明二者的区别:

  1. 并发:一个人工作时候可以在写代码、听音乐和玩游戏三个任务中任意切换,但是你的大脑不能在同一时间处理任何两件事情。

  2. 并行:并行则是假如一个人有2个大脑,可以同时写代码、听音乐或玩游戏。

在并发环境下, 由于程序的封闭性被打破,出现了以下特点:

(1) 并发程序之间有相互制约的关系。直接制约体现为一个程序需要另一个程 序的计算结果,间接制约体现为多个程序竞争共享资源,如处理器、缓冲区等。

(2) 并发程序的执行过程是断断续续的。程序需要记忆现场指令及执行点。

(3) 当并发数设置合理并且 CPU 拥有足够的处理能力时,并发会提高程序的运行效率。

2.何为线程安全

线程安全是指程序的并发执行状态下,多个线程对共享数据进行操作时,不会因为线程交替执行和切换执行顺序,导致数据不一致、不合法或出现其他不确定状态。

为了实现线程安全,通常采用互斥机制,例如锁、信号量等,保证同一时刻只有一个线程访问共享数据,避免产生数据不一致的问题。

线程安全的核心理念就是“要么只读,要么加锁”。

3.如何理解锁

乐观锁假定其他事务不会对数据产生冲突,因此在修改数据之前不会对数据加锁。相反,它在修改数据时使用版本号或其他机制来检测冲突,如果发生冲突,则事务回滚。

悲观锁假定其他事务将对数据产生冲突,因此在访问数据时对数据加锁。悲观锁通常导致其他事务等待,直到锁被释放,因此它可能影响性能。

总的来说,乐观锁适用于并发性较高的环境,而悲观锁适用于并发性较低的环境,因为它更容易控制冲突。

下面是一个使用乐观锁的简单示例程序:​​​

import time

class OptimisticLockExample:
    def __init__(self, initial_value=0, version=0):
        self.value = initial_value
        self.version = version

    def update(self, new_value, current_version):
        if self.version != current_version:
            raise Exception("Version conflict")
        time.sleep(1) # Simulate a slow database update operation
        self.value = new_value
        self.version += 1

if __name__ == "__main__":
    example = OptimisticLockExample()

    # Transaction 1
    current_version = example.version
    try:
        example.update(10, current_version)
        print("Transaction 1 successfully updated the value to 10")
    except Exception as e:
        print("Transaction 1 failed:", str(e))

        # Transaction 2
    current_version = example.version
    try:
        example.update(20, current_version)
        print("Transaction 2 successfully updated the value to 20")
    except Exception as e:
        print("Transaction 2 failed:", str(e))

上面的代码定义了一个类 OptimisticLockExample,该类具有两个属性:value 和 version。每次修改数据时,都会对当前的版本号进行检查,如果版本号不匹配,则会引发异常。

在代码的主程序中,创建了一个 OptimisticLockExample 对象,并尝试两次对该对象进行更新,打印出交易是否成功。

下面是一个使用悲观锁的简单示例程序:

import threading
import time

class PessimisticLockExample:
    def __init__(self, initial_value=0):
        self.value = initial_value
        self.lock = threading.Lock()

    def update(self, new_value):
        with self.lock:
            time.sleep(1) # Simulate a slow database update operation
            self.value = new_value

if __name__ == "__main__":
    example = PessimisticLockExample()

    # Transaction 1
    try:
        example.update(10)
        print("Transaction 1 successfully updated the value to 10")
    except Exception as e:
        print("Transaction 1 failed:", str(e))

    # Transaction 2
    try:
        example.update(20)
        print("Transaction 2 successfully updated the value to 20")
    except Exception as e:
        print("Transaction 2 failed:", str(e))

上面的代码定义了一个类 PessimisticLockExample,该类具有一个属性 value 和一个互斥锁 lock。每次修改数据时,都会使用 with 语句对锁进行上锁,保证同一时刻只有一个线程在修改数据。

在代码的主程序中,我们创建了一个 PessimisticLockExample 对象,并尝试两次对该对象进行更新,打印出交易是否成功。

最后: 下方这份完整的软件测试视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取 【保证100%免费】

在这里插入图片描述

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值