2010-06-11 13 views
5

निम्नलिखित परीक्षण कोड (एफ #) परिणाम नहीं लौटा रहा है मैं उम्मीद थी:.NET 4 spinlock

let safeCount() = 
    let n = 1000000 
    let counter = ref 0 
    let spinlock = ref <| SpinLock(false) 
    let run i0 i1() = 
    for i=i0 to i1-1 do 
     let locked = ref false 
     try 
     (!spinlock).Enter locked 
     if !locked then 
      counter := !counter + 1 
     finally 
     if !locked then 
      (!spinlock).Exit() 
    let thread = System.Threading.Thread(run 0 (n/2)) 
    thread.Start() 
    run (n/2) n() 
    thread.Join() 
    !counter 

मैं SpinLock परस्पर काउंटर बाहर करने के लिए और, इसलिए, यह वापस जाने के लिए के लिए उम्मीद थी 1,000,000 की संख्या, लेकिन, इसके बजाय, यह छोटे मान लौटाता है जैसे कि कोई पारस्परिक बहिष्करण नहीं हो रहा है।

कोई विचार क्या गलत है?

उत्तर

3

संपादित करें: स्टीफन स्वेंसेन के पास नीचे एक रेफरी शैली स्पिनलॉक तक पहुंचने का एक तरीका है। ! structs की एक प्रति देता है इसलिए इस मामले में उपयोग नहीं किया जाना चाहिए।

आप एक वर्ग यह काम करता है (मैं कोई लाभ नहीं हुआ एक स्थिर और अपरिवर्तनीय spinlock उपयोग करने की कोशिश)

type SpinLockClass() = 
    let s = System.Threading.SpinLock(false) 
    member x.Enter locked = s.Enter(locked) 
    member x.Exit() = s.Exit() 

let safeCount() = 
    let n = 1000000 
    let counter = ref 0 
    let spinlock = SpinLockClass() 
    let run i0 i1() = 
    for i=i0 to i1-1 do 
     let locked = ref false 
     try 
     spinlock.Enter locked 
     if !locked then 
      counter := !counter + 1 
     finally 
     if !locked then 
      spinlock.Exit() 
    let thread = System.Threading.Thread(run 0 (n/2)) 
    thread.Start() 
    run (n/2) n() 
    thread.Join() 
    !counter 
+0

धन्यवाद। ऐसा लगता है कि कक्षाओं में खेतों की प्रतिलिपि नहीं बनाई गई है लेकिन बाकी सब कुछ। यदि यह सही है तो यह जटिल अंकगणित जैसे अन्य अनुप्रयोगों के लिए भी प्रभाव डालता है, जहां आप स्ट्रक्चर की प्रतिलिपि से बचना चाहते हैं (और सी # वर्तमान में एफ # से बहुत तेज है)। –

8

स्पिनलॉक एक मूल्य प्रकार है। जब आप अपने स्पिन लॉक वैरिएबल (! स्पिनलॉक) को कम करते हैं, तो स्ट्रक्चर की प्रतिलिपि बनाई जाती है, और आपके द्वारा दर्ज/लॉक में लॉक अब अलग होता है।

+0

क्या इसे हल किया जा सकता है? –

10

कारण है कि spinlock struct की नकल की जा रही है क्योंकि है में spinlock लपेट कर सकते हैं! एक कार्य है: किसी फ़ंक्शन में तर्क के रूप में पारित होने पर या किसी फ़ंक्शन से लौटाए जाने पर (या उस मामले के किसी अन्य प्रकार के असाइनमेंट) के रूप में पारित होने पर structs की प्रतिलिपि बनाई जाती है। हालांकि, यदि आप सीधे रेफ सेल के सामग्री तक पहुंचते हैं, तो कोई प्रतिलिपि नहीं होती है।

let safeCount() = 
    let n = 1000000 
    let counter = ref 0 
    let spinlock = ref <| SpinLock(false) 
    let run i0 i1() = 
    for i=i0 to i1-1 do 
     let locked = ref false 
     try 
     spinlock.contents.Enter locked 
     if !locked then 
      counter := !counter + 1 
     finally 
     if !locked then 
      spinlock.contents.Exit() 
    let thread = System.Threading.Thread(run 0 (n/2)) 
    thread.Start() 
    run (n/2) n() 
    thread.Join() 
    !counter