क्या जावा रेगेक्स थ्रेड सुरक्षित है?


104

मेरे पास एक फ़ंक्शन है जो पैटर्न के लिए स्ट्रिंग्स की एक सूची की खोज Pattern#compileऔर उपयोग करता है Matcher

इस फ़ंक्शन का उपयोग कई थ्रेड्स में किया जाता है। प्रत्येक थ्रेड को बनाया जाने पर एक अद्वितीय पैटर्न पास होगा Pattern#compile। थ्रेड्स और पैटर्न की संख्या गतिशील है, जिसका अर्थ है कि मैं Patternकॉन्फ़िगरेशन के दौरान अधिक एस और थ्रेड्स जोड़ सकता हूं ।

synchronizeअगर मुझे regex का उपयोग करना है, तो क्या मुझे इस फ़ंक्शन पर डाल देना चाहिए ? क्या जावा थ्रेड में रेगेक्स सुरक्षित है?

जवाबों:


132

हां , पैटर्न क्लास के लिए जावा एपीआई प्रलेखन से

इस (पैटर्न) वर्ग के उदाहरण अपरिवर्तनीय हैं और कई समवर्ती धागे द्वारा उपयोग के लिए सुरक्षित हैं। ऐसे उपयोग के लिए माचिस वर्ग के उदाहरण सुरक्षित नहीं हैं।

यदि आप प्रदर्शन केंद्रित कोड देख रहे हैं, तो नए इंस्टेंस बनाने के बजाय, रीसेट () विधि का उपयोग करके मिलान उदाहरण को रीसेट करने का प्रयास करें। यह मैचर इंस्टेंस की स्थिति को रीसेट कर देगा, जिससे यह अगले रेगेक्स ऑपरेशन के लिए उपयोग योग्य हो जाएगा। वास्तव में, यह माचिस उदाहरण में बनाए रखा गया राज्य है जो समवर्ती पहुँच के लिए असुरक्षित होने के लिए ज़िम्मेदार है।


17
पैटर्न ऑब्जेक्ट थ्रेड सुरक्षित हैं, लेकिन compile()विधि नहीं हो सकती है। इन वर्षों में दो या तीन कीड़े हो गए हैं जो बहुपरत वातावरण में असफलता का कारण बनते हैं। मैं संकलित ब्लॉक में संकलन करने की सलाह दूंगा।
एलन मूर

4
हां, पैटर्न क्लास में कॉन्सेप्ट बग्स उठाए गए हैं, और साइक्रोनाइज्ड एक्सेस की आपकी सलाह की सराहना की जाती है। हालांकि, पैटर्न वर्ग के मूल डेवलपर्स का उद्देश्य पैटर्न वर्ग को धागा के रूप में सुरक्षित बनाना है, और यह अनुबंध है कि किसी भी जावा प्रोग्रामर पर भरोसा करने में सक्षम होना चाहिए। फ्रैंक होने के लिए, मेरे पास थ्रेड स्थानीय चर होंगे और अनुबंध द्वारा थ्रेड सुरक्षित व्यवहार पर भरोसा करने की तुलना में न्यूनतम प्रदर्शन हिट को स्वीकार करें (जब तक कि मैंने कोड नहीं देखा है)। जैसा कि वे कहते हैं "थ्रेडिंग आसान है, सही सिंक्रनाइज़ेशन कठिन है"।
विनीत रेनॉल्ड्स

1
ध्यान दें कि "पैटर्न" का स्रोत Oracle JDK वितरण में है ( oracle.com/technetwork/java/faq-141681.html#A14 के अनुसार : "जावा 2 SDK, मानक संस्करण में ही src.ip नामक एक फ़ाइल है। जावा पैकेज में सार्वजनिक वर्गों के लिए स्रोत कोड शामिल है ") ताकि कोई भी त्वरित झटके ले सके।
डेविड टोनहोफर

@DavidTonhofer मुझे लगता है कि हमारे नवीनतम JDK में सही बग-मुक्त कोड हो सकता है, लेकिन चूंकि Java के मध्यवर्ती .class फ़ाइलों को किसी भी संगत VM द्वारा किसी भी प्लेटफ़ॉर्म पर व्याख्या की जा सकती है, आप सुनिश्चित नहीं कर सकते कि उन सुधारों का उस रनटाइम में अस्तित्व है। बेशक, ज्यादातर समय आप जानते हैं कि सर्वर किस संस्करण में चल रहा है, लेकिन हर एक संस्करण की जांच करना कठिन है।
टीडब्लूआरब्रोब

12

जावा में नियमित अभिव्यक्ति के साथ थ्रेड-सुरक्षा

सारांश:

जावा नियमित अभिव्यक्ति एपीआई को एक एकल संकलित पैटर्न को कई मैच संचालन में साझा करने की अनुमति देने के लिए डिज़ाइन किया गया है।

आप अलग-अलग थ्रेड से एक ही पैटर्न पर सुरक्षित रूप से प्रतिमान () को कॉल कर सकते हैं और सुरक्षित रूप से मिलानकर्ताओं का उपयोग कर सकते हैं। Pattern.matcher () तुल्यकालन के बिना मिलान के निर्माण के लिए सुरक्षित है। यद्यपि यह पद्धति सिंक्रनाइज़ नहीं है, पैटर्न वर्ग के लिए आंतरिक, संकलित नामक एक अस्थिर चर हमेशा एक पैटर्न के निर्माण के बाद सेट किया जाता है और कॉल टू स्टार्टर टू मैचर () में पढ़ा जाता है यह किसी भी धागे को उस वस्तु की सामग्री को सही ढंग से "देखने" के लिए संदर्भित करता है।

दूसरी ओर, आपको विभिन्न थ्रेड्स के बीच एक मिलान साझा नहीं करना चाहिए। या कम से कम, यदि आपने कभी किया है, तो आपको स्पष्ट सिंक्रनाइज़ेशन का उपयोग करना चाहिए।


2
@akf, BTW, आपको ध्यान देना चाहिए कि यह एक चर्चा स्थल है (यह बहुत पसंद है)। मुझे लगता है कि आपको जो भी जानकारी मिली है, उससे बेहतर या बुरा कुछ भी आप यहां पाएंगे (यानी, यह जेम्स गोसलिंग का वन ट्रू वर्ड नहीं है)।
बॉब क्रॉस

3

जबकि आपको यह याद रखने की आवश्यकता है कि थ्रेड सुरक्षा को आसपास के कोड को भी ध्यान में रखना है, आप भाग्य में हैं। तथ्य यह है कि मैचर्स पैटर्न के मिलान कारखाने विधि का उपयोग करके बनाए गए हैं और सार्वजनिक निर्माणकर्ताओं की कमी एक सकारात्मक संकेत है। इसी तरह, आप कंपाइलिंग पैटर्न को बनाने के लिए कंपाइल स्टेटिक विधि का उपयोग करते हैं

तो, संक्षेप में, यदि आप उदाहरण की तरह कुछ करते हैं:

Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();

आपको बहुत अच्छा करना चाहिए।

स्पष्टता के लिए कोड उदाहरण के लिए अनुवर्ती: ध्यान दें कि इस उदाहरण का तात्पर्य यह है कि मिलानकर्ता इस प्रकार बनाया गया पैटर्न और परीक्षण के साथ थ्रेड-लोकल है। यानी, आपको मिलानकर्ता को इस तरह से किसी अन्य थ्रेड्स के लिए तैयार नहीं करना चाहिए।

सच कहूं तो, यह किसी भी थ्रेड-सुरक्षा प्रश्न का जोखिम है। वास्तविकता यह है कि यदि आप पर्याप्त प्रयास करते हैं तो किसी भी कोड को थ्रेड-असुरक्षित बनाया जा सकता है। सौभाग्य से, ऐसी अद्भुत पुस्तकें हैं जो हमें ऐसे तरीके सिखाती हैं जिनसे हम अपना कोड बर्बाद कर सकते हैं। यदि हम उन गलतियों से दूर रहते हैं, तो हम समस्याओं को फैलाने की अपनी संभावना को बहुत कम कर देते हैं।


@ जैसन एस: आंतरिक सुरक्षा थ्रेड सुरक्षित नहीं होने पर भी थ्रेड लोकेलिटी, थ्रेड सुरक्षा प्राप्त करने का एक बहुत ही सरल तरीका है। यदि एक बार में केवल एक ही विधि संभवत: किसी विशेष विधि तक पहुंच सकती है, तो आपने थ्रेड सुरक्षा को बाहरी रूप से लागू किया है।
बॉब क्रॉस

1
ठीक है, तो आप केवल यह कह रहे हैं कि उपयोग के बिंदु पर एक स्ट्रिंग से एक पैटर्न को फिर से बनाना, इसे संगृहीत करने के लिए बेहतर है संगोष्ठी के मुद्दों से निपटने के जोखिम में? मैं तुम्हें वह अनुदान दूँगा। मैं कारखाने के तरीकों और सार्वजनिक निर्माणकर्ताओं के बारे में उस वाक्य से उलझन में था, जो इस विषय पर एक लाल हेरिंग डब्ल्यू / आर / टी की तरह लगता है।
जेसन एस

@ जैसन एस, नहीं, कारखाने के तरीके और निर्माणकर्ताओं की कमी कुछ ऐसे तरीके हैं जिनसे आप अन्य धागों के साथ युग्मन के खतरे को कम कर सकते हैं। यदि आप मेरे पैटर्न के साथ जाने वाले माचिस का एकमात्र तरीका p.matcher () के माध्यम से प्राप्त कर सकते हैं, तो कोई भी आपके मिलानकर्ता को साइड-इफेक्ट नहीं कर सकता है। हालांकि, मैं अभी भी अपने लिए परेशानी खड़ी कर सकता हूं: अगर मेरे पास एक सार्वजनिक तरीका है जो उस मैचर को लौटाता है, तो एक और धागा उस पर मिल सकता है और इसे साइड-इफेक्ट कर सकता है। संक्षेप में, संक्षिप्तता कठिन है (किसी भी भाषा में)।
बॉब क्रॉस

2

कोड के लिए एक त्वरित नज़र, Matcher.javaपाठ सहित मेल खाने वाले सदस्य चर का एक समूह दिखाता है, समूहों के लिए सरणियाँ, स्थान बनाए रखने के लिए कुछ अनुक्रमित और booleanअन्य राज्य के लिए कुछ एस। यह सब एक स्टेटफुल की ओर इशारा Matcherकरता है जो कई लोगों द्वारा एक्सेस किए जाने पर अच्छा व्यवहार नहीं करेगा Threads। तो क्या JavaDoc :

इस श्रेणी के उदाहरण कई समवर्ती धागों द्वारा उपयोग के लिए सुरक्षित नहीं हैं।

यह केवल एक समस्या है, यदि @ याकूब क्रॉस के रूप में बताते हैं, तो आप अपने रास्ते से Matcherअलग Threadएस का उपयोग करने की अनुमति देते हैं । यदि आपको ऐसा करने की आवश्यकता है, और आपको लगता है कि सिंक्रनाइज़ेशन आपके कोड के लिए एक मुद्दा होगा, तो आपके पास एक विकल्प है कि आप प्रति कार्य सूत्र ThreadLocalबनाए रखने के लिए स्टोरेज ऑब्जेक्ट का उपयोग करें Matcher


1

योग करने के लिए, आप पुन: उपयोग कर सकते हैं (स्टैटिक वेरिएबल्स में) संकलित प्रतिमान (ओं) को रखें और उन्हें बताएं कि नए स्ट्रिंगर को देने के लिए जब कुछ स्ट्रिंग के खिलाफ रेगेक्स पैटेंस को मान्य करने की आवश्यकता होती है।

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Validation helpers
 */
public final class Validators {

private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";

private static Pattern email_pattern;

  static {
    email_pattern = Pattern.compile(EMAIL_PATTERN);
  }

  /**
   * Check if e-mail is valid
   */
  public static boolean isValidEmail(String email) { 
    Matcher matcher = email_pattern.matcher(email);
    return matcher.matches();
  }

}

देखें http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using- अनियमित-expressions-in-java/ (अंत के पास) RegEx पैटर्न के बारे में जो ई-मेल को सत्यापित करने के लिए ऊपर इस्तेमाल किया गया है ( यदि यह ई-मेल सत्यापन के लिए उपयुक्त नहीं है तो यह यहाँ पोस्ट किया गया है)


3
अपना उत्तर पोस्ट करने के लिए धन्यवाद! कृपया सेल्फ-प्रमोशन पर अक्सर पूछे जाने वाले प्रश्नों को ध्यान से पढ़ें । कोई व्यक्ति इस उत्तर और लिंक किए गए ब्लॉग पोस्ट को देख सकता है और सोच सकता है कि आपने ब्लॉग पोस्ट को केवल इसलिए पोस्ट किया है ताकि आप इसे यहां से लिंक कर सकें।
एंड्रयू बार्बर

2
क्यों परेशान static {}? आप उस चर आरंभीकरण को इनलाइन कर सकते हैं और Pattern finalसाथ ही बना सकते हैं।
ट्वीस्टेरोब

1
मैं TWiStErRob के दूसरे पर जुल्म करता हूं: private static final Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);बेहतर है।
क्रिस्टोफ रूसो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.