Global bir değişkeni iş parçacığı ile nasıl paylaşabilirim?
Python kod örneğim şu şekildedir:
from threading import Thread
import time
a = 0 #global variable
def thread1(threadname):
#read variable "a" modify by thread 2
def thread2(threadname):
while 1:
a += 1
time.sleep(1)
thread1 = Thread( target=thread1, args=("Thread-1", ) )
thread2 = Thread( target=thread2, args=("Thread-2", ) )
thread1.join()
thread2.join()
İki iş parçacığının tek bir değişkeni paylaşmasını nasıl sağlayacağımı bilmiyorum.
Sadece thread2
içinde a
yı global olarak bildirmeniz gerekir, böylece bu fonksiyon için yerel olan bir a
yı değiştirmemiş olursunuz.
def thread2(threadname):
global a
while True:
a += 1
time.sleep(1)
thread1de,
adeğerini değiştirmeye çalışmadığınız sürece özel bir şey yapmanıza gerek yoktur (bu, global olanı gölgeleyen yerel bir değişken yaratır; gerekirse
global a` kullanın)>
def thread1(threadname):
#global a # Optional if you treat a as read-only
while a < 10:
print a
Bir fonksiyonda:
a += 1
derleyici tarafından assign to a => Create local variable a
şeklinde yorumlanacaktır, ki bu sizin istediğiniz şey değildir. Muhtemelen a not initialized
hatası ile başarısız olacaktır, çünkü (yerel) a gerçekten başlatılmamıştır:
>>> a = 1
>>> def f():
... a += 1
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'a' referenced before assignment
İstediğinizi (çok hoş karşılanmayan ve iyi nedenlerle) global
anahtar sözcüğü ile elde edebilirsiniz, bunun gibi:
>>> def f():
... global a
... a += 1
...
>>> a
1
>>> f()
>>> a
2
Ancak genel olarak, son derece hızlı bir şekilde kontrolden çıkan global değişkenleri kullanmaktan kaçınmalısınız. Ve bu özellikle thread1
inizin a
nın ne zaman değiştirildiğini bilmesi için herhangi bir senkronizasyon mekanizmasına sahip olmadığınız çok iş parçacıklı programlar için geçerlidir. Kısacası: iş parçacıkları karmaşıktır ve iki (veya daha fazla) iş parçacığı aynı değer üzerinde çalışırken olayların hangi sırada gerçekleştiğini sezgisel olarak anlamayı bekleyemezsiniz. Dil, derleyici, işletim sistemi, işlemci... hepsi bir rol oynayabilir ve hız, pratiklik veya başka herhangi bir nedenle işlem sırasını değiştirmeye karar verebilir.
Bu tür şeyler için uygun yol Python paylaşım araçlarını kullanmaktır (locks ve arkadaşlar) veya daha iyisi, verileri paylaşmak yerine bir Queue aracılığıyla iletin, örneğin bu şekilde:
from threading import Thread
from queue import Queue
import time
def thread1(threadname, q):
#read variable "a" modify by thread 2
while True:
a = q.get()
if a is None: return # Poison pill
print a
def thread2(threadname, q):
a = 0
for _ in xrange(10):
a += 1
q.put(a)
time.sleep(1)
q.put(None) # Poison pill
queue = Queue()
thread1 = Thread( target=thread1, args=("Thread-1", queue) )
thread2 = Thread( target=thread2, args=("Thread-2", queue) )
thread1.start()
thread2.start()
thread1.join()
thread2.join()
Koşu örneği:
UYARI! BUNU ASLA EVDE/İŞTE YAPMAYIN! Sadece sınıfta ;)
Acele durumlardan kaçınmak için semaforlar, paylaşılan değişkenler vb. kullanın.
from threading import Thread
import time
a = 0 # global variable
def thread1(threadname):
global a
for k in range(100):
print("{} {}".format(threadname, a))
time.sleep(0.1)
if k == 5:
a += 100
def thread2(threadname):
global a
for k in range(10):
a += 1
time.sleep(0.2)
thread1 = Thread(target=thread1, args=("Thread-1",))
thread2 = Thread(target=thread2, args=("Thread-2",))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
ve çıktı:
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 2
Thread-1 3
Thread-1 3
Thread-1 104
Thread-1 104
Thread-1 105
Thread-1 105
Thread-1 106
Thread-1 106
Thread-1 107
Thread-1 107
Thread-1 108
Thread-1 108
Thread-1 109
Thread-1 109
Thread-1 110
Thread-1 110
Thread-1 110
Thread-1 110
Thread-1 110
Thread-1 110
Thread-1 110
Thread-1 110
Zamanlama doğru olsaydı, `a += 100
işlemi atlanırdı:
İşlemci T a+100`` değerinde çalışır ve 104 değerini alır. Ancak durur ve bir sonraki iş parçacığına atlar Burada, T+1'de a'nın eski değeri olan
a+1yürütülür,
a == 4. Yani 5 değerini hesaplar. Geri atlayın (T+2'de), thread 1, ve ```a=104
değerini belleğe yazın.
Şimdi thread 2'ye geri dönün, zaman T+3'tür ve belleğe `a=5
yazın.
İşte bu kadar! Bir sonraki yazdırma komutu 104 yerine 5 yazdıracaktır.
Çoğaltılması ve yakalanması gereken ÇOK kötü bir böcek.