测开必备知识:线程安全和线程不安全

文摘   教育   2024-09-03 10:25   北京  

什么是线程安全

线程安全指的是在多线程环境下,一个对象或者数据结构能够保证在并发访问时依然能够维持其预期的行为,不会出现数据不一致或者其他意外情况。

反之就是线程不安全。

多线程环境下可能产生的问题
当多个线程同时访问共享的资源(比如对象、变量、数据结构等)时,可能会引发以下问题:
1.竞态条件(Race Condition):当多个线程试图同时访问和修改共享资源时,由于操作的顺序不确定,导致最终结果不可预测。
2.数据竞争(Data Race):当一个线程在写入数据的同时,另一个线程在尝试读取或写入同一块数据时,可能会导致数据不一致的问题。
3.死锁(Deadlock):当多个线程相互等待对方释放资源的情况,导致所有线程都无法继续执行的状态。
4.内存一致性错误(Memory Consistency Errors):由于缓存一致性等问题,导致不同线程看到的共享变量的值不同步。
使用python展示一个线程不安全的例子
import threading
class Counter: def __init__(self): self.value = 0
def increment(self): self.value += 1
def worker(counter): for _ in range(1000000): counter.increment()
counter = Counter()threads = []for _ in range(10): thread = threading.Thread(target=worker, args=(counter,)) threads.append(thread) thread.start()
for thread in threads: thread.join()
print("Final counter value:", counter.value)
代码解释:
在这个例子中,我们有一个简单的计数器类Counter,它具有一个increment()方法用于递增计数器的值。然后我们创建了10个线程,每个线程都会调用increment()方法来递增计数器的值1000000次,理论上输出值应该是1000000。最后,我们打印出计数器的最终值发现并不是我们期望的1000000,可能是小于1000000的值。由于Python中的+=操作不是原子性的,多个线程可能同时读取并修改计数器的值,导致竞态条件,从而使最终的计数器值可能不正确,这个就是线程不安全导致的原因。

我们修改一下代码,将代码从线程不安全改为线程安全,代码如下:

import threading
class SafeCounter: def __init__(self): self.value = 0 self.lock = threading.Lock()
def increment(self): with self.lock: self.value += 1
def safe_worker(counter): for _ in range(1000000): counter.increment()
safe_counter = SafeCounter()safe_threads = []for _ in range(10): thread = threading.Thread(target=safe_worker, args=(safe_counter,)) safe_threads.append(thread) thread.start()
for thread in safe_threads: thread.join()
print("Final safe counter value:", safe_counter.value)

在这个例子中,我们对Counter类进行了修改,添加了一个锁lock。在increment()方法中,我们使用with self.lock:语句来确保在同一时间只有一个线程能够修改计数器的值。这样就避免了竞态条件,从而使得计数器的值在多线程环境下是正确的。

执行的结果:

想学习测试开发的朋友,请添加吴老师微信:wulaoshi1978

光荣之路
关注光荣之路软件技术培训账号,即时收取测试开发技术的免费公开课信息,各大公司测试及开发招聘信息、最新的技术咨询、线下测试技术分享沙龙信息
 最新文章