هل ستتعارض أقفال الفئة وأقفال الكائنات؟ هل ستتعارض أقفال الكائنات والأقفال الخاصة؟ التوضيح من خلال الأمثلة.
1. الاتفاقيات ذات الصلة
من أجل توضيح الوصف التالي، قمنا أولاً بوضع الاتفاقيات التالية بشأن التعريفات ذات الصلة بالأقفال الواردة في هذه المقالة:
1. قفل الفئة: أضف أقفالًا ثابتة ومتزامنة إلى الطرق الموجودة في الكود، أو مقاطع التعليمات البرمجية المتزامنة (xxx.class)، مثل increament() أدناه؛
2. قفل الكائن: أضف قفلًا متزامنًا إلى الطريقة الموجودة في الكود، أو مقطع كود متزامن (هذا)، مثل SynOnMethod () وsynInMethod () أدناه؛
3. القفل الخاص: قم بتعريف خاصية خاصة مثل قفل الكائن الخاص داخل الفصل، وقم بمزامنة (قفل) مقطع التعليمات البرمجية الذي يحتاج إلى القفل، مثل SynMethodWithObj() أدناه.
2. رمز الاختبار
1. اكتب ObjectLock فئة بدء التشغيل
انسخ رمز الكود كما يلي:
فئة عامة ObjectLock {
public static void main(String[] args) {
System.out.println("وقت البدء = " + System.currentTimeMillis()+"ms");
اختبار LockTestClass = جديد LockTestClass();
لـ (int i = 0; i < 3; i++) {
Thread thread = new ObjThread(test, i);
Thread.start();
}
}
}
2. اكتب فئة مؤشر ترابط ObjThread لبدء طريقة المزامنة (لاحظ أنه يمكن تعديل طريقة تشغيلها لاختبارات مختلفة)
انسخ رمز الكود كما يلي:
الطبقة العامة ObjThread تمتد الموضوع {
قفل LockTestClass؛
كثافة العمليات ط = 0؛
public ObjThread(LockTestClass lock, int i) {
this.lock = lock;
this.i = i;
}
تشغيل الفراغ العام () {
//طريقة غير مقفلة
//lock.noSynMethod(this.getId(),this);
// طريقة قفل الكائن 1، باستخدام SynInMethod المتزامن
lock.synInMethod();
// طريقة قفل الكائن 2، باستخدام الطريقة المتزامنة (هذه).
//lock.synOnMethod();
// طريقة القفل الخاص، باستخدام طريقة (الكائن) المتزامنة
//lock.synMethodWithObj();
// طريقة قفل الفئة، باستخدام طريقة الزيادة المتزامنة الثابتة
LockTestClass.increment();
}
}
3. اكتب فئة اختبار قفل أخرى LockTestClass، بما في ذلك طرق القفل المختلفة
انسخ رمز الكود كما يلي:
الطبقة العامة LockTestClass {
// يستخدم لحساب قفل الفصل
int الخاص الثابت i = 0;
// قفل خاص
كائن كائن خاص = كائن جديد ()؛
/**
* <ص>
* طريقة خالية من القفل
*
* @param معرف الموضوع
* @ موضوع المعلمة
*/
الفراغ العام noSynMethod (معرف الخيط الطويل، مؤشر ترابط ObjThread) {
System.out.println("nosyn: فئة obj هي " + thread + "، threadId هو"
+ معرف الخيط)؛
}
/**
* طريقة قفل الكائن 1
*/
SynOnMethod () باطلة عامة متزامنة {
System.out.println("synOnMethod يبدأ" + "، الوقت = "
+ System.currentTimeMillis() + "ms");
يحاول {
Thread.sleep(2000L);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.println("synOnMethod ينتهي");
}
/**
* طريقة قفل الكائن 2، استخدم المزامنة (هذا) للقفل
*/
الفراغ العام SynInMethod () {
متزامن (هذا) {
System.out.println("synInMethod يبدأ" + "، الوقت = "
+ System.currentTimeMillis() + "ms");
يحاول {
Thread.sleep(2000L);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.println("synInMethod ينتهي");
}
}
/**
* طريقة قفل الكائن 3
*/
SynMethodWithObj () باطلة عامة {
متزامن (كائن) {
System.out.println("synMethodWithObj يبدأ" + "، الوقت = "
+ System.currentTimeMillis() + "ms");
يحاول {
Thread.sleep(2000L);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.println("synMethodWithObj ينتهي");
}
}
/**
* قفل الفصل
*/
زيادة الفراغ المتزامن الثابت العام () {
System.out.println("الفصل متزامن.i = " + i + "، الوقت = "
+ System.currentTimeMillis() + "ms");
أنا++;
يحاول {
Thread.sleep(2000L);
} قبض على (InterruptedException e) {
printStackTrace();
}
System.out.println("نهاية متزامنة للفئة.");
}
}
3. نتائج الاختبار
1. لاختبار أقفال الفئة وأقفال الكائنات، قم بتعديل طريقة تشغيل ObjectThread كما يلي:
انسخ رمز الكود كما يلي:
تشغيل الفراغ العام () {
//طريقة غير مقفلة
//lock.noSynMethod(this.getId(),this);
// طريقة قفل الكائن 1، باستخدام SynInMethod المتزامن
lock.synInMethod();
// طريقة قفل الكائن 2، باستخدام الطريقة المتزامنة (هذه).
//lock.synOnMethod();
// طريقة القفل الخاص، باستخدام طريقة (الكائن) المتزامنة
//lock.synMethodWithObj();
// طريقة قفل الفئة، باستخدام طريقة الزيادة المتزامنة الثابتة
LockTestClass.increament();
}
الإخراج الطرفي:
انسخ رمز الكود كما يلي:
وقت البدء = 1413101360231 مللي ثانية
يبدأ SynInMethod، الوقت = 1413101360233ms
ينتهي SynInMethod
فئة متزامنة أنا = 0، الوقت = 1413101362233ms
يبدأ SynInMethod، الوقت = 1413101362233ms
ينتهي الفصل المتزامن.
ينتهي SynInMethod
الطبقة متزامنة أنا = 1، الوقت = 1413101364233ms
يبدأ SynInMethod، الوقت = 1413101364233ms
ينتهي الفصل المتزامن.
ينتهي SynInMethod
الطبقة متزامنة أنا = 2، الوقت = 1413101366234 مللي ثانية
ينتهي الفصل المتزامن.
يمكنك أن ترى أن طريقة قفل الكائن (synInMothod) أسرع بثانيتين من طريقة قفل الفئة (الزيادة) عند بدء تشغيلها لأول مرة، وذلك لأنه عند تنفيذ SynInMehtod، فإنه ينام لمدة ثانيتين ثم ينفذ الزيادة، وهذان الأمران. تشترك الأساليب في نفس الموضوع، لذا ستكون الزيادة أبطأ بمقدار ثانيتين إذا تم وضع الزيادة أمام SynInMethod قيد التشغيل، فستكون الزيادة أسرع بمقدار ثانيتين عند بدء التشغيل لأول مرة.
عند بدء تشغيل طريقة قفل الفئة، تبدأ أيضًا طريقة قفل الكائن لخيط آخر في نفس الوقت تقريبًا، مما يشير إلى أن الاثنين لا يستخدمان نفس القفل ولن تكون هناك منافسة.
الخلاصة: لن تتنافس أقفال الفئة وأقفال الكائنات، ولن تؤثر طرق القفل الخاصة بها على بعضها البعض.
2. الأقفال الخاصة وأقفال الكائنات، يتم تعديل طريقة تشغيل ObjectThread على النحو التالي:
انسخ رمز الكود كما يلي:
تشغيل الفراغ العام () {
//طريقة غير مقفلة
//lock.noSynMethod(this.getId(),this);
// طريقة قفل الكائن 1، باستخدام SynInMethod المتزامن
lock.synInMethod();
// طريقة قفل الكائن 2، باستخدام الطريقة المتزامنة (هذه).
//lock.synOnMethod();
// طريقة القفل الخاص، باستخدام طريقة (الكائن) المتزامنة
lock.synMethodWithObj();
// طريقة قفل الفئة، باستخدام طريقة الزيادة المتزامنة الثابتة
//LockTestClass.increament();
}
الإخراج الطرفي:
انسخ رمز الكود كما يلي:
وقت البدء = 1413121912406 مللي ثانية
يبدأ SynInMethod، الوقت = 1413121912407 مللي ثانية.
ينتهي SynInMethod.
يبدأ SynMethodWithObj، الوقت = 1413121914407ms
يبدأ SynInMethod، الوقت = 1413121914407 مللي ثانية.
ينتهي SynInMethod.
ينتهي SynMethodWithObj
يبدأ SynInMethod، الوقت = 1413121916407 مللي ثانية.
يبدأ SynMethodWithObj، الوقت = 1413121916407ms
ينتهي SynInMethod.
ينتهي SynMethodWithObj
يبدأ SynMethodWithObj، الوقت = 1413121918407ms
ينتهي SynMethodWithObj
يشبه إلى حد كبير أقفال الفئة وأقفال الكائنات.
الخلاصة: الأقفال الخاصة وأقفال الكائنات لن تتنافس، ولن تؤثر طرق القفل الخاصة بها على بعضها البعض.
3. تتم إضافة المزامنة مباشرة إلى الطريقة ومزامنتها (هذا)، ويتم تعديل طريقة تشغيل ObjectThread على النحو التالي:
انسخ رمز الكود كما يلي:
تشغيل الفراغ العام () {
//طريقة غير مقفلة
//lock.noSynMethod(this.getId(),this);
// طريقة قفل الكائن 1، باستخدام SynInMethod المتزامن
lock.synInMethod();
// طريقة قفل الكائن 2، باستخدام الطريقة المتزامنة (هذه).
lock.synOnMethod();
// طريقة القفل الخاص، باستخدام طريقة (الكائن) المتزامنة
//lock.synMethodWithObj();
// طريقة قفل الفئة، باستخدام طريقة الزيادة المتزامنة الثابتة
//LockTestClass.increament();
}
الإخراج الطرفي:
انسخ رمز الكود كما يلي:
وقت البدء = 1413102913278 مللي ثانية
يبدأ SynInMethod، الوقت = 1413102913279 مللي ثانية
ينتهي SynInMethod
يبدأ SynInMethod، الوقت = 1413102915279 مللي ثانية
ينتهي SynInMethod
يبدأ SynOnMethod، الوقت = 1413102917279 مللي ثانية
ينتهي SynOnMethod
يبدأ SynInMethod، الوقت = 1413102919279 مللي ثانية
ينتهي SynInMethod
يبدأ SynOnMethod، الوقت = 1413102921279 مللي ثانية
ينتهي SynOnMethod
يبدأ SynOnMethod، الوقت = 1413102923279 مللي ثانية
ينتهي SynOnMethod
كما ترون، يتم إخراج الاثنين بشكل تسلسلي صارم (بالطبع، لا يتم تحديد ما إذا كان يتم تشغيل SynInMethod أو SynOnMethod أولاً عند التنفيذ مرة أخرى، اعتمادًا على من حصل على القفل).
الاستنتاج: تمت إضافة المزامنة مباشرة إلى الطريقة والمزامنة (هذا) لقفل الكائن الحالي. طريقتا القفل في علاقة تنافسية، ولا يمكن تنفيذ سوى طريقة واحدة في نفس الوقت.