常见的原子操作有哪些?
在多线程编程或并发编程中,为了避免出现竞态条件(Race Condition),我们通常会使用原子操作。原子操作是指在程序执行时不可中断的操作,也就是说,该操作一旦开始就一定会执行完毕,不会被其他线程打断。
那么,常见的原子操作有哪些呢?下面进行详细讲解。
1. 加法和减法操作
加法操作和减法操作都是常见的原子操作。在多线程场景下,我们一般使用加法操作和减法操作来对共享的变量进行累加和减少操作,以避免出现竞态条件。
代码示例:
import threading
def add_count():
global count
for i in range(100000):
count += 1
def dec_count():
global count
for i in range(100000):
count -= 1
count = 0
t1 = threading.Thread(target=add_count)
t2 = threading.Thread(target=dec_count)
t1.start()
t2.start()
t1.join()
t2.join()
print(count)
上面代码中,我们定义了两个函数 add_count
和 dec_count
,用来对全局变量 count
进行加 1 和减一操作。然后我们创建了两个线程 t1
和 t2
,分别执行 add_count
和 dec_count
函数。最后我们通过 print
函数输出 count
的值。这个例子中就展示了加法和减法操作在多线程中的应用。
2. Compare-and-swap (CAS) 操作
Compare-and-swap 操作是指先比较内存中的值和期望值是否相同,如果相同就将新值写入内存中,否则不做任何操作。在多线程编程中,CAS 操作是一种原子操作,可以避免出现竞态条件。
代码示例:
import threading
def add_count():
global count
for i in range(100000):
while True:
old_val = count
new_val = old_val + 1
if compare_and_swap(count, old_val, new_val):
break
def dec_count():
global count
for i in range(100000):
while True:
old_val = count
new_val = old_val - 1
if compare_and_swap(count, old_val, new_val):
break
def compare_and_swap(val, old_val, new_val):
if val == old_val:
val = new_val
return True
else:
return False
count = 0
t1 = threading.Thread(target=add_count)
t2 = threading.Thread(target=dec_count)
t1.start()
t2.start()
t1.join()
t2.join()
print(count)
上面的代码中,我们首先定义了 CAS 操作函数 compare_and_swap
,用来比较内存中的值和期望值,如果相同就更新为新值。然后我们定义了 add_count
和 dec_count
函数,分别调用 compare_and_swap
函数实现加 1 和减 1 操作。最后我们还是用两个线程去执行这两个函数,并输出 count
值。
总结
原子操作是多线程编程必不可少的一部分,使用原子操作可以避免出现竞态条件,提高程序的并发性能。以上我们介绍了两种常见的原子操作:加法和减法操作以及 Compare-and-swap (CAS) 操作。在使用时,我们可以根据具体的需求选择不同的原子操作。