2009-11-12 87 views
1

我試圖讓我的代碼塊非線程安全,以便玩弄一些我希望稍後添加的異常。這個python代碼是線程安全的嗎?

這是我的Python代碼:

from time import sleep 
from decimal import * 
from threading import Lock 
import random 

def inc_gen(c): 
    """ 
    Increment generator 
    """ 
    while True: 
     #getting sleep period 
     timing_rand = random.randrange(0,1000) 
     print "INC: Sleeping for " + str(Decimal(timing_rand)/Decimal(1000)) 
     sleep(Decimal(timing_rand)/Decimal(1000)) 
     c.inc() 
     yield c 

def dec_gen(c): 
    """ 
    decrement generator 
    """ 
    while True: 
     #getting sleep period 
     timing_rand = random.randrange(0,1000) 
     print "DEC: Sleeping for " + str(Decimal(timing_rand)/Decimal(1000)) 
     sleep(Decimal(timing_rand)/Decimal(1000)) 
     c.dec() 
     yield c 

class something(): 
    """ 
    We use an obj instead of an atomic variable c, we can have "threads" 
    simulating shared resources, instead of a single variable, to avoid 
    atomic instructions. (which is thread-safe in python thanks to GIL) 
    """ 
    def __init__(self): 
     self.c = 0 
    def inc(self): 
     self.c += 1 
    def dec(self): 
     self.c -= 1 
    def value(self): 
     return self.c 

def main(): 
    """ 
    main() function 
    """ 
    obj = something() 
    counters = [inc_gen(obj),dec_gen(obj)] 

    #we only want inc_gen 10 times, and dec_gen 10 times. 
    inc = 0 #number of times inc_gen is added 
    dec = 0 #number of times dec_gen is added 

    while True: 
     #choosing the next counter 
     if inc < 10 and dec < 10: 
      counter_rand = random.randrange(0,2) 
      if counter_rand == 0: 
       inc += 1 
      else: dec += 1 
     elif inc < 10 and dec == 10: 
      inc += 1 
      counter_rand = 0 
     elif dec < 10 and inc == 10: 
      dec += 1 
      counter_rand = 1 
     else: break 

     counters[counter_rand].next() 

    #print for testing 
    print "Final value of c: " + str(obj.value()) 

if __name__ == "__main__": 
    main() 

有代碼可能導致其不爲0

它是線程安全的最終值我希望它做的是什麼?如果不是,我該如何使它不是線程安全的?

+2

呃,你剛纔問過這個(http://stackoverflow.com/questions/1717393),並且得到了答案。你爲什麼用示例代碼問完全相同的問題,這些代碼在邏輯上相同但不必要更復雜? – 2009-11-12 09:13:10

回答

0

基本上,您有讀取 - 修改 - 寫入操作。如果你想確保事情變得不合時宜,最好的辦法就是延遲閱讀和寫作之間的延遲。

def inc(self): 
    v = self.c 
    time.sleep(random.random()) # Should probably limit it to a few hundred ms 
    self.c = v + 1 

def dec(self): 
    v = self.c 
    time.sleep(random.random()) # Should probably limit it to a few hundred ms 
    self.c = v - 1 
+0

使用睡眠不會將任何非線程安全代碼轉換爲線程安全代碼,它只會降低同時訪問關鍵資源的可能性 – 2016-05-10 09:08:30

+0

您可以在downvoting之前閱讀問題和答案......我從未說過它會使它線程安全! OP也沒有讓線程安全。恰恰相反,這裏的重點在於使它失敗的可能性在於它的非線程安全性...... – 246tNt 2016-05-27 13:15:17

+0

ahem,你是對的。對不起,我反應太快了。我在驗收測試中遭受了沉重的打擊......我試圖取消downvote,但除非答案被修改,否則我不能。 – 2016-05-30 07:42:55