2009-05-22 4 views
11

स्कूल में एक परियोजना के लिए, हम जावा 5.0 में एक बहुप्रचारित सर्वर बना रहे हैं। यह परियोजना सर्वर के समवर्ती पहलू पर केंद्रित है।जावा: ServerSocket.accept थ्रेडसेफ है?

हमारे पास अनुरोधों का इलाज करने के लिए समर्पित कुछ धागे हैं। ऐसा करने के लिए, उनके पास नए कनेक्शन स्वीकार करने के लिए ServerSocket.accept() पर कॉल है। हमारी पसंद उनमें से एक समूह शुरू करना था और इन्हें आने वाले कनेक्शनों को इस धारणा के साथ इलाज करना था कि दो धागे एक ही समय में एक ही कनेक्शन को स्वीकार नहीं कर सकते हैं।

लेकिन अब मुख्य समस्या यह है कि हमें एपीआई में कुछ भी नहीं मिल रहा है जो हमें इस व्यवहार की गारंटी देता है (या हमने सही नहीं देखा) और हमारे पास "यह काम करता है" सबूत को छोड़कर कुछ भी नहीं है।

क्या कोई जावा विधियों पर इस तरह की जानकारी देखने के लिए स्रोत है?

+0

हम जानते हैं कि यह डिज़ाइन वास्तव में अच्छा नहीं है और हमने इसे पहले से ही वर्कर थ्रेड के पूल का उपयोग करने के लिए बदल दिया है। अब हमारे पास केवल एक धागा है जो कार्यकर्ता धागे को अनुरोध स्वीकार करता है और भेजता है। मुझे अभी भी पता चलेगा कि जावा विधियों की थ्रेड-सुरक्षा के बारे में कहीं जानकारी है या नहीं। –

उत्तर

25

लघु जवाब:

आपका कोड कुछ इस तरह दिखता चाहिए अगर प्रलेखन निर्दिष्ट नहीं करता है कि कुछ धागा सुरक्षित है, तो आप यह मान लेना चाहिए कि ऐसा नहीं है। आपको यह सुनिश्चित करने के लिए धागे के बीच समन्वय करने की आवश्यकता है कि एक ही समय में कोई भी दो धागे सर्वर सॉकेट का उपयोग न करें।

यह विशेष रूप से महत्वपूर्ण है क्योंकि कुछ अन्य कोड ServerSocket.setSocketFactory के साथ अपना सॉकेट कार्यान्वयन पंजीकृत कर सकते थे। भले ही डिफ़ॉल्ट सॉकेट कार्यान्वयन थ्रेड-सुरक्षित है, कस्टम कार्यान्वयन होना आवश्यक नहीं है। दस्तावेज में कुछ भी नहीं है जो ऐसा कहता है।

लांग जवाब: डिफ़ॉल्ट विंडोज कार्यान्वयन

आप डाउनलोड करने और java SE 1.6 source code निरीक्षण कर सकते हैं।

मैंने \j2se\src\share\classes\java\net\ServerSocket.java पर शुरू किया और वहां से निशान PlainSocketImpl.java तक पहुंचा। PlainSocketImpl.Accept विधि को native के रूप में चिह्नित किया गया है।

विंडोज़ के लिए देशी सी ++ कोड \j2se\src\windows\native\java\net\PlainSocketImpl.c में है। यह winsock accept फ़ंक्शन का उपयोग करता है। एक MSDN article on WinSock (जोर मेरा) से:

Windows NT और Windows 2000 के तहत, 16-बिट अनुप्रयोगों के लिए विंडोज सॉकेट समर्थन WINSOCK.DLL पर आधारित है। 32-बिट अनुप्रयोगों के लिए, समर्थन WSOCK32.DLL में है। दिए गए एपीआई समान हैं कि 32-बिट संस्करणों में पैरामीटर 32 बिट्स तक बढ़ गए हैं। Win32 के तहत, थ्रेड सुरक्षा आपूर्ति की गई है।

तो कम से कम खिड़कियों पर, Socket.Accept अर्थ में सुरक्षित है कि यह दो धागे में एक ही कनेक्शन स्वीकार नहीं दूँगी धागा है। ServerSocket कार्यान्वयन में बुनियादी ढांचा भी है (ई।जी। बंद() विधि लॉक का उपयोग करती है) जो इंगित करती है कि इसका उद्देश्य थ्रेड सुरक्षित होना है।

+2

+1 इस महान उत्तर के लिए फिर से +1 – talonx

+0

के लिए – Kartoch

8

यह आपके प्रश्न का काफी जवाब नहीं देता है, लेकिन एकाधिक धागे पर स्वीकार() चल रहा है जैसे सर्वर के डिज़ाइन में कुछ गड़बड़ है।

आमतौर पर एकाधिक धागे से स्वीकार() को चलाने की आवश्यकता नहीं होनी चाहिए।

while (serverIsUpAndRunning()) 
{ 
    // Wait for an incoming connection. 
    Socket s = serverSocket.accept(); 
    // Spawn a thread to handle the socket, 
    // so that we don't block new connections. 
    SocketHandlerThread t = new SocketHandlerThread(s); 
    t.start(); 
} 
+0

प्रत्येक कार्यकर्ता धागा अपने स्वयं के कनेक्शन को स्वीकार कर रहा है एक पूरी तरह से वैध डिजाइन है। यह अन्य धागे को सौंपने से लाभ नहीं होता है। –

+1

आप एक निश्चित थ्रेडपूल के बारे में सोच रहे हैं जहां प्रत्येक धागा स्वीकृति() के लिए प्रतिस्पर्धा करता है? यह निश्चित रूप से सामान्य धागा स्वामित्व का एक उलटा है। मुझे यह स्वीकार करना होगा कि मैं नहीं देख सकता कि कैसे एक नए धागे (या थ्रेडपूल से एक) को "सौंपने की लागत" कैसे ज्यादातर मामलों में जटिलता को औचित्य साबित करेगी। क्या ऐसे कोई उदाहरण हैं जहां इस प्रकार का डिज़ाइन व्यावहारिक है? – Nuoji

+3

अधिक महत्वपूर्ण बात यह है कि जावा * स्वीकृति की थ्रेड सुरक्षा की गारंटी नहीं देता है - तथ्य यह है कि मूलभूत एपीआई विंडोज़ में करता है (स्वीकृत उत्तर द्वारा उद्धृत), अर्थहीन है। विस्तृत, अच्छी तरह से शोध किए गए उत्तर –