يمكن تحقيق التزامن متعدد الخيوط في JAVA من خلال البيان المتزامن. باستخدام كتل التعليمات البرمجية المتزامنة، يضمن JVM أن مؤشر ترابط واحد فقط يمكنه الاحتفاظ بالقفل على كائن معين في نفس الوقت. تتيح آلية القفل لخيوط متعددة الوصول بأمان إلى الموارد الهامة.
يتم كتابة رمز المزامنة على النحو التالي:
الكود 1:
Object obj = new Object()... syncronized(obj) { // TODO: الوصول إلى الموارد الهامة} إن تعدد مؤشرات الترابط في JAVA دائمًا ما يكون مليئًا بالفخاخ. إذا استخدمنا Boolean ككائن متزامن، فقد تحدث الحالتان التاليتان:
1. يُعتقد أن كائنًا واحدًا مقفلاً، لكن الكائنات المختلفة تتم مزامنتها فعليًا.
الكود 2:
Private volatile isTrue = false; publich void aMethod() { ... syncronized(isTrue) { isTrue =!isTrue; // TODO: الوصول إلى الموارد المهمة isTrue = !isTrue } ... } للوهلة الأولى، لا يوجد خطأ في الكود أعلاه، نظرًا لاستخدام المزامنة (isTrue)، يمكن لخيط واحد فقط الوصول إلى الموارد المهمة في نفس الوقت، ولكن هذا ليس هو الحال. لأن الثوابتين خطأ وصحيح يتوافقان مع كائنين مختلفين. عندما يتغير isTrue، فمن المحتمل أن تقوم سلاسل مختلفة بمزامنة كائنات مختلفة. ستتغير الملاكمة التلقائية لـ JAVA من false إلى Boolean.FALSE وصحيح إلى Boolean.TRUE (وهذا يوضح أيضًا أنه إذا تم تغيير false إلى Boolean.FALSE، فستكون النتيجة هي نفسها). اكتب كود الاختبار لأحد الحالات المذكورة أعلاه كما يلي:
الكود 3:
public class BooleanTest { public volatile Boolean isTrue = Boolean.FALSE // إنه نفس الشيء إذا كنت تستخدم خطأ هنا public void aMethod() { for(int i=0;i<10;i++) { Thread t = new Thread() { public void run() { syncronized(isTrue) { isTrue = !isTrue; System.out.println(Thread.currentThread().getName() + " - isTrue=" + isTrue); حاول{ Double run = 1000 * Math.random(); Thread.sleep(ran.intValue()); }catch(InterruptedException e) {} if(!isTrue) System.out.println( Thread.currentThread().getName() + " - أوه، لا!"); isTrue = !isTrue } } }; t.start(); } } public static void main(String... args) { BooleanTest bt = new BooleanTest(); عند تشغيل الكود أعلاه، سترى "-أوه، لا!"، من وقت لآخر، للإشارة إلى أن سلاسل الرسائل المختلفة تدخل إلى كتلة التعليمات البرمجية المتزامنة في نفس الوقت.
2. يُعتقد أن كائنات مختلفة تتم مزامنتها، ولكنها في الواقع كائن واحد.
في بعض الأحيان قد نرغب في المزامنة على كائنات متعددة، إذا تم استخدام Boolean ككائن متزامن، فمن المحتمل أن كتلتي المزامنة التي لا ينبغي أن يكون لهما علاقة تستخدم نفس قفل الكائن. الأمثلة هي كما يلي:
الكود 4:
public volatile aBoolean = Boolean.FALSE; .. متزامن (anotherBoolean) { // المهام: الوصول إلى المورد الحرج 2 } ... } افترض أنه سيتم استدعاء طريقة وطريقة أخرى في الأصل بواسطة مجموعتين من سلاسل الرسائل غير المرتبطة. ومع ذلك، نظرًا لأن Boolean.FALSE وfalse يشيران إلى نفس الكائن، فقد يتم حظر الوصول إلى المورد الحرج 2 بواسطة المورد الحرج 1 (والعكس صحيح).
تشير الحالتان أعلاه إلى أنه عند استخدام الكتل المتزامنة، حاول عدم استخدام كائنات منطقية ككائنات متزامنة، وإلا فقد تحدث مشكلات غير متوقعة، أو قد تحدث اعتراضات في تعديلات التعليمات البرمجية المستقبلية.
ويمكن أيضًا أن نرى من هذا أن أي مزامنة للثوابت تكون محفوفة بالمخاطر. إذا كان يجب عليك مزامنة منطقية، فيجب عليك استخدام عامل التشغيل الجديد لإنشاء كائن منطقي.