:: faskは問題が神話の各ビュー機能のためのグローバルな要求が要求されているが、要求は、データ障害の現象が発生することはありませんでしたか??
#グローバルwzgの修正のために同時にローカル、オープン10個のスレッドを実行し、この場合には、私が実行した結果を見てのようになりますか?
スレッディングインポートスレッド
インポート時間
WZG = -1
DEF タスク(アルギニン):
株式会社参加無料WZG
WZG =のArg
#、しばらくの間ブロックされ、完成したスレッドの値を右の最終的な実装を実行するためにどのスレッド、結果はグローバルwzgを変更します、他のスレッド結果がすべて同じであるので、結果のレビューは、改ざんされ
time.sleep(2)
印刷(WZG)用 Iにおけるレンジ(10):
Tはスレッドを=(目標=タスク、引数=(I))
t.start( )「」 '
#9すべての結果、修正wzg改ざんされるので、他のスレッドが、
このような状況の原因理由は次のとおりです。
任意のマークなしで、同じ変数wzgでグローバルに動作する複数のスレッドは、スレッドのそれと区別することができますによって引き起こされる混乱の結果、すべての回の修理の値の値を変更するスレッド他のスレッドの前に実行する最後がどうなるかを変更する
ので、印刷その結果、最後のスレッドが値変更
要求にフラスコを、セッションではない混乱の各要求神話のビューにもグローバル変数でありますか?
ここでは、ローカル・オブジェクトの使用を見てみましょう
' 『』
#ローカルオブジェクト
からスレッディングインポートスレッド
からスレッドインポートローカル
「」「
スレッドID1ストレージ{に相当するスレッド、に基づいて区別」「{」引数「: 1}、」 スレッドID2' { 『引数』: 2}、「スレッドID3」{「引数」: } 3}
、プリントアウトがそうデータの混乱を防ぐために、スレッドに対応する値である
の## {Argで:. 1}
' 『』
インポート時間
LQZ =ローカル()
DEF :タスク(アルギニン)
lqz.arg = Argで
time.sleep( 2)
プリント(lqz.arg)
用 Iにおける範囲(10):
Tはスレッド=(目標=タスク、引数の=(I))
t.start()
#自定义local,函数版
from threading import get_ident,Thread #get_ident线程的ID号
import time
storage = {}
def set(k,v):
#获取线程的id号
# storage={'线程id1': {'args': 1}, '线程id2': {'args': 2}, '线程id3': {'args': 3}}
#这样子存起来的值就对应各自的线程
ident = get_ident()
print(ident)
if ident in storage:
storage[ident][k] = v
else:
storage[ident] = {k:v}
def get(k):
ident = get_ident()
return storage[ident][k]
def task(arg):
set('val',arg)
v = get('val')
print(v)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
#面向对象版的local
from threading import get_ident,Thread
import time
#{'线程id1': {'args': 1}, '线程id2': {'args': 2}, '线程id3': {'args': 3}}
class Local(object):
storage = {}
def set(self, k, v):
ident = get_ident()
if ident in Local.storage:
Local.storage[ident][k] = v
else:
Local.storage[ident] = {k: v}
def get(self, k):
ident = get_ident()
return Local.storage[ident][k]
obj = Local()
def task(arg):
obj.set('val',arg)
v = obj.get('val')
time.sleep(1)
print(v)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
#改进版本1
from threading import get_ident,Thread
import time
class Local(object):
storage = {}
def __setattr__(self, k, v):
ident = get_ident()
if ident in Local.storage:
Local.storage[ident][k] = v
else:
Local.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return Local.storage[ident][k]
obj = Local()
# obj2=Local() #谢谢对象用的都是同一个字典
# obj3=Local()
# obj4=Local()
# obj5=Local()
def task(arg):
obj.val = arg
time.sleep(1)
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
上面那个用的全是类的字典,不管生成几个对象,用的都是同一个,也有可能造成数据错乱
所以我们希望每次生成local对象用的都是自己的字典,所以对上面的继续改进2
改进版2
from threading import get_ident,Thread
import time
class Local(object):
def __init__(self): #将字典放在init中,这样每个对象用的都是自己的字典,但是要注意黄色部分的写法会出现一直递归,报错,
object.__setattr__(self,'storage',{}) #这里直接调用父类的__setattr__方法
#这样写会出现递归,该出调用__setattr__,se
# self.storage={}
def __setattr__(self, k, v):
ident = get_ident()
if ident in self.storage:
self.storage[ident][k] = v
else:
self.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return self.storage[ident][k]
obj = Local()
def task(arg):
obj.val = arg
# obj.xxx = arg
time.sleep(1)
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()
到此为止,自己写了一个local对象,只支持线程
#改进版3即支持协程又支持线程
try:
#getcurrent 获取协程id
from greenlet import getcurrent as get_ident
except Exception as e:
from threading import get_ident
from threading import Thread
import time
class Local(object):
def __init__(self):
object.__setattr__(self,'storage',{})
def __setattr__(self, k, v):
ident = get_ident()
if ident in self.storage:
self.storage[ident][k] = v
else:
self.storage[ident] = {k: v}
def __getattr__(self, k):
ident = get_ident()
return self.storage[ident][k]
obj = Local()
def task(arg):
obj.val = arg
obj.xxx = arg
print(obj.val)
for i in range(10):
t = Thread(target=task,args=(i,))
t.start()