2009-08-03 14 views
13

क्या सेमफोर 0 से कम हो सकता है? मेरा मतलब है, कहें कि मेरे पास एन = 3 के साथ एक सेमफोर है और मैं 4 बार "डाउन" कहता हूं, तो एन 0 रहेगा लेकिन एक प्रक्रिया अवरुद्ध हो जाएगी?सैमफोर कैसे काम करता है?

और वैसे ही, अगर शुरुआत में मैं कॉल करता हूं, तो क्या एन 3 से अधिक हो सकता है? क्योंकि जैसा कि मैंने इसे देखा है, अगर एन शुरुआत में 3 से अधिक हो सकता है तो मैं दो बार फोन करता हूं, फिर बाद में मैं जितना बार कर सकता हूं उससे अधिक बार कॉल कर सकता हूं, इस प्रकार महत्वपूर्ण खंड में अधिक प्रक्रियाएं डालता हूं तो सेमफोर मुझे अनुमति देता है ।

अगर कोई मेरे लिए थोड़ा सा स्पष्टीकरण देगा तो मैं बहुत सराहना करता हूं।

ग्रेग

+0

यह भी देखें http://stackoverflow.com/questions/184147/countdownlatch-vs-semaphore – finnw

उत्तर

6

नीचे कॉलिंग जब यह 0 से काम नहीं करना चाहिए। जब यह 3 काम करता है तो कॉल करना। (मैं जावा के बारे में सोच रहा हूँ)।

मुझे कुछ और जोड़ने दें। बहुत से लोग ताले के बारे में सोचते हैं जैसे (बाइनरी) सेमफोर (यानी - एन = 1, इसलिए सेमफोर का मूल्य या तो 0 (आयोजित) या 1 (आयोजित नहीं) है)। लेकिन यह बिल्कुल सही नहीं है। लॉक में "स्वामित्व" की धारणा होती है, इसलिए यह "पुनर्वित्त" हो सकती है। इसका मतलब है कि एक धागा जिसमें ताला होता है, को फिर से लॉक() को कॉल करने की अनुमति दी जाती है (प्रभावी रूप से 0 से -1 तक गिनती को स्थानांतरित कर दिया जाता है), क्योंकि थ्रेड पहले से ही लॉक रखता है और इसे "पुन: प्राप्त करने" की अनुमति है। ताले भी गैर पुनर्वित्तक हो सकते हैं। लॉक धारक से अनलॉक() को लॉक() के समान संख्या में कॉल करने की उम्मीद है।

सेमफोरों के स्वामित्व की कोई धारणा नहीं है, इसलिए वे पुनर्वित्त नहीं कर सकते हैं, हालांकि उपलब्ध कई परमिट प्राप्त किए जा सकते हैं। इसका मतलब है कि किसी थ्रेड को ब्लॉक करने की आवश्यकता होती है जब यह 0 के मान से मुकाबला करता है, जब तक कोई सेमफोर में वृद्धि नहीं करता है।

इसके अलावा, मैंने जो देखा है (जो जावा है) में, आप एन से अधिक सेमफोर को बढ़ा सकते हैं, और यह भी स्वामित्व के साथ करना है: एक सेमफोर के पास स्वामित्व की कोई धारणा नहीं है, इसलिए कोई भी इसे और दे सकता है परमिट। धागे के विपरीत, जहां भी एक थ्रेड लॉक किए बिना अनलॉक() को कॉल करता है, यह एक त्रुटि है। (जावा में यह एक अपवाद फेंक देगा)।

आशा है कि इसके बारे में सोचने का यह तरीका मदद करता है।

16

(java.util.concurrent.Semaphore से शब्दावली जावा टैग दी का उपयोग करना। इन विवरणों में से कुछ कार्यान्वयन-विशिष्ट। मुझे लगता है अपने "नीचे", जावा सेमाफोर के acquire() तरीका है और कर रहे हैं अपने "ऊपर" release() है।)

हाँ, acquire() करने के लिए अपने आखिरी कॉल जब तक एक और धागा release() कॉल करने या अपने धागा बाधित है रोकेंगे।

हां, आप release() अधिक बार कॉल कर सकते हैं, फिर कम से कम java.util.concurrent.Semaphore के साथ।

सेमफोर के कुछ अन्य कार्यान्वयनों में परमिट की "अधिकतम" संख्या का विचार हो सकता है, और उस अधिकतम से अधिक रिलीज करने के लिए कॉल विफल हो जाएगा। जावा Semaphore वर्ग एक रिवर्स स्थिति की अनुमति देता है, जहां एक सेमफोर परमिट की नकारात्मक संख्या से शुरू हो सकता है, और कॉल तब तक असफल हो जाएंगे जब तक पर्याप्त release() कॉल न हो जाएं। एक बार परमिट की संख्या गैर-नकारात्मक हो गई है, यह फिर कभी नकारात्मक नहीं होगी।

+0

क्या ऋणात्मक सेमफोर कृत्यों को गिनती की तरह कहना सुरक्षित है? आखिरी रिलीज (गणना = 0) तक पहुंचने पर प्रभावी रूप से मैं कुछ भी नहीं कर सकता। या क्या कोई अन्य उपयोगकाज है जहां मैं नकारात्मक सेमफोर का उपयोग करना चाहता हूं? – jtkSource

+0

@jtk स्रोत: मुझे एक ऑफहैंड के बारे में पता नहीं है। –

1

बस एन को अपने सीमित संसाधन की गणना करने वाले काउंटर के रूप में देखें। चूंकि आपके पास संसाधनों की नकारात्मक संख्या नहीं हो सकती है, एन अवशेष> = 0. यदि आपके उपलब्ध संसाधनों की संख्या में परिवर्तन होता है, तो अधिकतम एन को भी बदला जाना चाहिए। मैं इसे किसी अन्य मामले में पहले इसे कम किए बिना एन बढ़ाने के लिए अच्छी शैली पर विचार नहीं करता।

2

हां, ऋणात्मक मान का मतलब है कि आपके पास सेमफोर को रिलीज़ होने की प्रतीक्षा की गई प्रक्रियाएं हैं। एक सकारात्मक मूल्य का मतलब है कि आप सेमफोर ब्लॉक से पहले कई बार अधिग्रहण कर सकते हैं।

आप इस तरह के मूल्य के बारे में सोच सकते हैं: एक सकारात्मक संख्या का मतलब है कि कई संसाधन उपलब्ध हैं। ऋणात्मक मूल्य का मतलब है कि इस समय सभी संसाधनों को उठाए जाने पर संसाधनों की आवश्यकता वाले कई संस्थाएं हैं। जब आप संसाधन प्राप्त करते हैं तो आप मूल्य कम करते हैं, जब आप इसे रिलीज़ करते हैं तो आप मान बढ़ाते हैं। यदि मूल्य अभी भी है> = 0 कमी के बाद आपको संसाधन मिलता है, अन्यथा आपकी इकाई को कतार में डाल दिया जाता है।

विकिपीडिया में सेमाफोर का एक अच्छा विवरण: http://en.wikipedia.org/wiki/Semaphore_(programming)

8

हाय ग्रेग उदाहरण निम्नलिखित पर विचार:

public static void (String [] args) फेंकता InterruptedException {

Semaphore available = new Semaphore(1, true); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 

    available.release(); 
    System.out.println("Released : " +available.availablePermits()); 

    available.release(); 
    System.out.println("Released : " +available.availablePermits()); 

    available.release(); 
    System.out.println("Released : " +available.availablePermits()); 

    available.release(); 
    System.out.println("Released : " +available.availablePermits()); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 

    available.acquire(); 
    System.out.println("Acquire : " +available.availablePermits()); 
} 

आप उत्पादन यू निम्नलिखित हो जाएगा देखते हैं, तो:

मोल: 0 जारी किया गया: 1 जारी किया गया: 2 जारी किया गया: 3 जारी किया गया: 4 प्राप्त करें: 3 प्राप्त करें: 2 प्राप्त करें: 1 प्राप्त करें: 0 और प्रतीक्षा चल रही है।

तो मूल रूप से हर रिलीज पर बढ़ाने के लिए और प्राप्त 0. एक बार जब यह 0 यह इंतजार करेंगे पर पहुंच गया जब तक यह कम हो जाएगा होगा की अनुमति जब तक रिलीज एक ही वस्तु :)

0

साथ java.util.concurrent.Semaphore का उपयोग पर कहा जाता है तरीके प्राप्त() और रिलीज(), मुझे लगता है कि परमिट हमेशा> = 0 होगा। आइए मान लें कि आप धागे को सिंक्रनाइज़ करना चाहते हैं ताकि लूप के लिए केवल 1 धागा अंदर हो। यदि सेम सेफफोर का प्रकार है जिसमें प्रारंभिक मान 1 है, तो यह 2 से अधिक धागे के लिए काम नहीं करेगा।

while(true){    

    sem.wait(); // wait is acquire 

    for(int i=0; i<=5; i++){ 

     try { 
      Thread.sleep(250); 
     }catch (InterruptedException e) {} 

     System.out.println("Thread "+ threadname+ " " + i); 

      } 
    sem.signal(); // signal is release } 

हालांकि, आप जावा से सेमफोर क्लास को कार्यान्वित कर सकते हैं और अपनी खुद की कक्षा बना सकते हैं जो इसकी अनुमति देता है।

package yourpackage; 

import java.util.concurrent.Semaphore; 

public class SemaphoreLayer { 
public Semaphore s=null; 
public String name; 
private int val; 

public SemaphoreLayer(int i){ 
    s=new Semaphore(i); val=i; 
} 

public void wait(){ 
try { 
    val--; 
    s.acquire(); 

    } catch (InterruptedException e) { 
    System.out.println("Error signal semaphorelayer"); 
}} 

public void signal(){ 
    if(val<0){val++;}{ 
     s.release(); 
     val++; 
    } 
} 

} 

अब वैल नकारात्मक हो सकता है। हालांकि, मुझे यकीन नहीं है कि यह पूरी तरह से सुरक्षित है, क्योंकि अगर हमारे पास एक धागे से संकेत है और दूसरे से प्रतीक्षा करें और वे वैल ++ और वैल का प्रयास करें - यह खराब हो सकता है। (इसके लिए संभावनाएं बहुत छोटी हैं लेकिन वे मौजूद हैं, इसलिए यदि आप कोडिंग कर रहे हैं और आपको 100% कोई त्रुटि नहीं है, तो मैं इस कोड का उपयोग करने की अनुशंसा नहीं करता) निष्कर्ष में यही कारण है कि मॉनीटर की अवधारणा का उपयोग करना बेहतर है जावा और कुंजी शब्द सिंक्रनाइज़ में।

संबंधित मुद्दे