# 列表与队列——谈谈线程安全

·  阅读 7187

### GIL下的线程不安全

``````import threading
import time
zero = 0
def change_zero():
global zero
for i in range(3000000):
zero += 1
zero -= 1

th1.start()
th2.start()
th1.join()
th2.join()
print(zero)

``````x = zero + 1
zero = x

``````初始：zero = 0
th1: x1 = zero + 1  # x1 = 1
th2: x2 = zero + 1  # x2 = 1
th2: zero = x2      # zero = 1
th1: zero = x1      # zero = 1  问题出在这里，两次赋值，本来应该加2变成了加1
th1: x1 = zero - 1  # x1 = 0
th1: zero = x1      # zero = 0
th2: x2 = zero - 1  # x2 = -1
th2: zero = x2      # zero = -1

### 原子操作

`zero += 1`这种一步可以被拆成多步的程序，就不是一个原子操作。不是原子操作的直接后果就是它没有完全执行结束，就有可能切换到其他线程，此时如果其他线程修改的是同一个变量，就有可能发生资源修改冲突。

``````def change_zero():
global zero
for i in range(1000000):
with lock:
zero += 1
zero -= 1

``````L.append(x)
L1.extend(L2)
x = L[i]
x = L.pop()
L1[i:j] = L2
L.sort()
x = y
x.field = y
D[x] = y
D1.update(D2)
D.keys()

``````i = i+1
L.append(L[-1])
L[i] = L[j]
D[x] = D[x] + 1

``````from dis import dis
a = 0
def fun():
global a
a = a + 1

dis(fun)

``````  5     0 LOAD_GLOBAL       0 (a)
7 STORE_GLOBAL      0 (a)
13 RETURN_VALUE

``````from dis import dis
l = []
def fun():
global l
l.append(1)

dis(fun)

``````  5    0 LOAD_GLOBAL       0 (l)
9 CALL_FUNCTION     1 (1 positional, 0 keyword pair)
12 POP_TOP
16 RETURN_VALUE

### python中常见队列对比

List VS Queue.Queue VS collections.deque

`collections.deque``list`的区别主要在于数据的插入与提取上。如果要将数据插入列表头部，或者从头部提取数据，则前者的效率远远高于后者，这是前者的双向队列特性，优势毋庸置疑。如果对提取的顺序无所谓，则没有必要一定要用`collections.deque`