سؤال

هل من الممكن في وقت التشغيل التحقق برمجيًا من اسم مؤشر الترابط الذي يحمل قفل كائن معين؟

هل كانت مفيدة؟

المحلول

يمكنك فقط معرفة ما إذا كان الخيط الحالي يحمل قفلًا عاديًا (Thread.holdsLock(Object)).لا يمكنك الحصول على إشارة إلى مؤشر الترابط الذي يحتوي على القفل بدون رمز أصلي.

ومع ذلك، إذا كنت تفعل أي شيء معقد فيما يتعلق بالترابط، فمن المحتمل أنك تريد التعرف على الحزم java.util.concurrent.ال ReentrantLock تسمح لك بالحصول على مالكها (لكنها طريقة محمية، لذا سيتعين عليك تمديدها).اعتمادًا على التطبيق الخاص بك، قد تجد أنه باستخدام حزم التزامن، لن تحتاج إلى الحصول على مالك القفل بعد كل شيء.

هناك طرق غير برمجية للعثور على مالكي القفل، مثل إرسال إشارة إلى JVM لإصدار تفريغ مؤشر ترابط إلى stderr، وهي مفيدة لتحديد سبب حالة التوقف التام.

نصائح أخرى

يمكنك الوصول إلى الأقفال التي تحملها الخيوط ذات الانعكاس.هذا يعمل فقط مع جافا 1.6.

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] ti = bean.getThreadInfo(bean.getAllThreadIds(), true, true);

يوجد في كل كائن من كائنات ThreadInfo كائنات LockInfo التي يمكنك استخدام الهويةHashCode عليها لمقارنتها بالقفل المعني.

يمكنك، بدءًا من الإصدار 1.6، استخدام JMX للقيام بجميع أنواع الأشياء المثيرة للاهتمام بما في ذلك العثور على الأقفال المعلقة.لا يمكنك الحصول على الكائن الفعلي، لكنك تحصل على قيمة تجزئة الفئة والهوية (وهي ليست فريدة).

يوجد مثال في إحدى مدونات الويب الخاصة بي.

يجري com.jconsole.يتم تضمينه في Java SDK ويتم تشغيله من سطر الأوامر.لست متأكدًا من نظام التشغيل الذي تستخدمه، ولكن على نظام التشغيل Windows، يمكنك فقط تمرير معرف عملية جافا إليه.من المفترض أن يساعدك في العثور على الخيط الذي يسبب المشكلة.أو يمكنك استخدام ملف تعريف تجاري مثل YourKit أو أي عدد من ملفات التعريف الأخرى.

في الإصدار 1.5، يمكنك العثور على جميع المواضيع والحصول على حالة كل منها، على سبيل المثال كما يلي:

    Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces();
    for (Map.Entry<Thread, StackTraceElement[]> threadEntry : map.entrySet()) {
        log.info("Thread:"+threadEntry.getKey().getName()+":"+threadEntry.getKey().getState());
        for (StackTraceElement element : threadEntry.getValue()) {
            log.info("--> "+element);
        }
    }

يمنحك Thread.getState معلومات حول ما إذا كان الموضوع محظورًا أو في انتظاره وما إلى ذلك، راجع jdk API ThreadState

يمكنك التحقق من القفل على كائن معين عن طريق الاتصال wait() أو notify() الطريقة على هذا الكائن.إذا كان الكائن لا يحمل القفل، فسوف يرمي llegalMonitorStateException .

2- بالاتصال holdsLock(Object o) طريقة.سيؤدي هذا إلى إرجاع القيمة المنطقية.

اذا كانت قفل إعادة الدخول يمكنك التحقق مما إذا كان مثبتًا بواسطة مؤشر الترابط الحالي

final ReentrantLock lock = new ReentrantLock();
lock.isHeldByCurrentThread();

يمكنك استخدام متغير للاحتفاظ بالخيط الحالي عندما تأخذ القفل، ثم طباعته إذا كان شخص آخر يحاول استخدامه.

Thread holderOfLock = null;
Object theLock = new Object();

public void doStuff()
{
    if(holderOfLock != null)
    {
       //get and print name of holderOfLock-thread or get stacktrace etc.
    }

    synchronized (theLock)
    {
        holderOfLock = Thread.currentThread();
        //do stuff...
        holderOfLock = null;
    }
}

قبيح ولكنه يعمل.

String findLockOwner(ReentrantLock lock) {
    String patternStr = "\\[Locked by thread (\\S+)\\]";
    Pattern pattern = Pattern.compile(patternStr);
    Matcher matcher = pattern.matcher(lock.toString());
    boolean matchFound = matcher.find();
    if (matchFound && matcher.groupCount() >= 1) {
      return matcher.group(1);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top