الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

النياسب و التزامن في جافا

مغلق
بدأه joo في 4 أغسطس 2005 · 4 رد · 735 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

النياسب و التزامن في جافا

ملاحظة :

نيسب Thread

اجرائية method

متصنت Listener

وعد جافا بأن تكون مستقلة عن قاعدة العمل ليس صحيح إطلاقاً

إذ إن أغلب البرامج التي تحوي واجهة مستخدم هي برامج متعددة النياسب ,و

النياسب في جافا للأسف ليس كما يعتقد أغلب المبرمجين مستقلة عن قاعدة العمل,وبالتالي جافا ليست مستقلة عن

منصة العمل.

حيث في الواجهات كل متصنت هو عبارة عن نيسب, وكذلك البرنامج الذي يحوي الطريقة

Main

هو نيسب أيضاً,وبالتالي أبسط البرامج يحوي نيسبين على الأقل

ولكن إن عدم استخدام النياسب بالشكل الصحيح يؤدي إلى بطئ شديد في الإستجابة , و هذا ما يكرهه أكثر المبرمجين

التزامن عملية مكلفة إذ إن تطبيق التزامن عملياًهو تطبيق سيمافور

و من استرتيجيات تنفيذ التزامن في جافا هي استخدام تعليمة

Assemply test_and_set which is an atomic operation

و هي تتم على مستوى نظام التشغيل ,

و هي تتم كما يلي : في حال عدم وجود تنافس على

Object

معين فإن الآلة الافتراضية في جافا تغوص في نظام التشغيل في البيئة المضيفة لتفحص بت معين يشير فيماإذا كان معلم أم لا ,في حال عدم تعليمه تقوم هي بتعليم هذا البت (أي إعطائه قيمة ما)

ولكن في حال وجود تنافس على

Object

معين فإن تغوص في نظام التشغيل في البيئة المضيفة لتفحص بت معين يشير فيماإذا كان معلم أم لا ,في حال كونه فعندها يتوجب على الآلة الافتراضية الخروج من نظام التشغيل لتعود لاحقاً و تفحص هذا البت

السيء في هذا الأمر هو إن عملية النفاذ لنظام التشغيل المضيف و الخروج منه هي عملية مكلفة جداً

مثال في

Windows NT it takes 600 machine cycles just to enter the operating system kernel

و إليكم المثال التالي الذي يوضح الفكرة السابقة :

package taming_java_threads;

import java.text.NumberFormat;

import java.util.*;

/**

*

* a benchmark to test the overhead of synchronization

* on a simple method invocation , Benchmarking java,paricularly

* when HotSpot is in the equation,is tricky.

* ther's a good tech note on this subject at http://...

**/

public class Synch {

private static long[] locking_time =new long[100];

private static long[] not_locking_time =new long[100];

private static final int ITERATIONS =1000000;

public Synch() {

}//END of constructor

/**

* this is synchronized method

* ***/

synchronized long locking (long a, long B){

return a+b;

}

/**

* this is nonsynchronized method

* ***/

long not_locking (long a, long B){

return a+b;

}

private void test(int id){

long start =System.currentTimeMillis();

for (long i=ITERATIONS;--i>=0;){

locking(i,i);//there is no contention

}

locking_time[id]=System.currentTimeMillis()-start;

start =System.currentTimeMillis();

for (long i=ITERATIONS;--i>=0;){

not_locking(i,i);//there is no synchronization

}

not_locking_time[id]=System.currentTimeMillis()-start;

}//end of test method

static void print_result(int id){

NumberFormat compositor =NumberFormat.getInstance();

compositor.setMaximumFractionDigits(2);

double timeInSynchronization =locking_time[id]-not_locking_time[id];

System.out.println("pass"+id+"\t:Time lost:"

+compositor.format(timeInSynchronization)+" ms\t"+

compositor.format((double)locking_time[id]/not_locking_time[id]*100)

+"% increase");

}//end of print_result

public static void main(String strrr []){

//first with no contention;

final Synch tester=new Synch();

tester.test(0);print_result(0);

tester.test(1);print_result(1);

tester.test(2);print_result(2);

tester.test(3);print_result(3);

tester.test(4);print_result(4);

tester.test(5);print_result(5);

tester.test(6);print_result(6);

/*

now let's do it again with contention . I'm assuming that

hotspot has optimized the test method by now , so am only calling it once

**/

final Object start_gate=new Object();

Thread t1=new Thread("number 1"){

public void run(){

try{

System.out.println("thread name : "+this.getName()+"\n");

synchronized(start_gate){start_gate.wait();

System.out.println(this.getName()+"\t after waiting\n");

}

}catch (InterruptedException e){}

System.out.println(this.getName()+"\t befor berforming test\n");

tester.test(7);

}//end of run

};//end of thread t1

Thread t2=new Thread ("number 2"){

public void run(){

try{

System.out.println("thread name : "+this.getName()+"\n");

synchronized(start_gate){start_gate.wait();

System.out.println(this.getName()+"\t after waiting\n");

}

}catch (InterruptedException e){}

System.out.println(this.getName()+"\t befor berforming test\n");

tester.test(8);

}

};

Thread .currentThread().setPriority(Thread.MIN_PRIORITY);

t1.start();

t2.start();

synchronized(start_gate){start_gate.notifyAll();}

try{

t1.join();

t2.join();

}catch (InterruptedException e){}

print_result(7);

print_result(8);

}

}

إذن يجب أن نكون حذرين عند استخدام التزامن وألا نستخدمه إلا عند الضرورة

فإذا كان لدينا اجرائية معينة تجري عملياتها فقط على متحولاتها الداخلية , و لا تنفذ للمتحولات العامة أو السكونية تبع الصف عندها يجب إلا تكون هذه الإجرائية متزامنة و إلا فإننا نضيع وقتنا على الفاضي...

أرجو أن تكونوا قد استفدتم من هذه الفكرة , و إذا أعجبكم الموضوع بإمكاننا متابعة النقاش فيه , و إلى اللقاء

#2

لوضوح القراءة!

package taming_java_threads;

import java.text.NumberFormat;
import java.util.*;
/**
*
* a benchmark to test the overhead of synchronization
* on a simple method invocation , Benchmarking java,paricularly
* when HotSpot is in the equation,is tricky.
* ther's a good tech note on this subject at http://...
**/

public class Synch {
	private static long[] locking_time =new long[100];
	private static long[] not_locking_time =new long[100];
	private static final int ITERATIONS =1000000;


	public Synch() {
	}//END of constructor

	/**
	* this is synchronized method
	* ***/
	synchronized long locking (long a, long b) {
  return a+b;
	}

	/**
	* this is nonsynchronized method
	* ***/
	long not_locking (long a, long b){
  return a+b;
	}

	private void test(int id){
  long start =System.currentTimeMillis();
  for (long i=ITERATIONS;--i>=0;){
 	 locking(i,i);//there is no contention
  }

  locking_time[id]=System.currentTimeMillis()-start;
  start =System.currentTimeMillis();

  for (long i=ITERATIONS;--i>=0;){
 	 not_locking(i,i);//there is no synchronization
  }
  not_locking_time[id]=System.currentTimeMillis()-start;
	}//end of test method

	static void print_result(int id){
  NumberFormat compositor =NumberFormat.getInstance();
  compositor.setMaximumFractionDigits(2);

  double timeInSynchronization =locking_time[id]-not_locking_time[id];

  System.out.println("pass"+id+"\t:Time lost:"
 	 +compositor.format(timeInSynchronization)+" ms\t"+
 	 compositor.format((double)locking_time[id]/not_locking_time[id]*100)
 	 +"% increase");

  }//end of print_result

	public static void main(String strrr []){
  //first with no contention;
  final Synch tester=new Synch();

  tester.test(0);print_result(0);
  tester.test(1);print_result(1);
  tester.test(2);print_result(2);
  tester.test(3);print_result(3);
  tester.test(4);print_result(4);
  tester.test(5);print_result(5);
  tester.test(6);print_result(6);
  /*
  now let's do it again with contention . I'm assuming that
  hotspot has optimized the test method by now , so am only calling it once
  **/
  final Object start_gate=new Object();
  Thread t1=new Thread("number 1"){
 	 public void run(){
    try{
   	 System.out.println("thread name : "+this.getName()+"\n");
   	 synchronized(start_gate){
      start_gate.wait();
      System.out.println(this.getName()+"\t after waiting\n");
   	 }
    }catch (InterruptedException e){}

    System.out.println(this.getName()+"\t befor berforming test\n");
    tester.test(7);
 	 }//end of run
  };//end of thread t1

  Thread t2=new Thread ("number 2"){
 	 public void run(){
    try{
   	 System.out.println("thread name : "+this.getName()+"\n");
   	 synchronized(start_gate){
      start_gate.wait();
      System.out.println(this.getName()+"\t after waiting\n");
   	 }
    }catch (InterruptedException e){}
    System.out.println(this.getName()+"\t befor berforming test\n");
    tester.test(8);

 	 }
  };

  Thread .currentThread().setPriority(Thread.MIN_PRIORITY);

  t1.start();
  t2.start();
  synchronized(start_gate){start_gate.notifyAll();}

  try{
 	 t1.join();
 	 t2.join();
  }catch (InterruptedException e){}
  print_result(7);
  print_result(8);

	}

}

تم تعديل هذه المشاركة بواسطة أبومازن في 4 أغسطس 2005 في 17:02

#3

موضوعك عبارة عن موضوعين:

الموضوع الأول أن النسيب غير مستقل عن النظام فهذا طبيعي! فالنسيبات تعمل على النظام فكيف تفصل؟!

لكن لتوضيح الأمر: أن تعاملك مع النسيب في الجافا واحد في كل الأنظمة، فلا تحتاج لمعرفة نوعية النظام! بهذا هو مستقل من هذه الناحية.. وبالطبع تنفيذ النسيبات تنفذ بصورة مختلفة من نظام إلى نظام ومن هذه الناحية هي غير مستقلة!

الموضوع الثاني: التزامن يأخذ وقتا، وهذا طبيعي جدا! فلو عندك 10 أشياء تريد نفس المعلومة وكانت المعلومة ليست متزامنة فلن يكون هناك تنافس! أما إذا كانت متزامنة فسيخدم كل على حدة وبهذا سيزيد الوقت كثيرا كثيرا!!

كلا الموضوعين، حسب علمي، ليس خاصا بالجافا، بل هو في البرمجة بشكل عام! توجد نفس المشكلة (إن كانت تسمى مشكلة) في جميع اللغات!

زبدة القول: أن نستعمل التزامن فقط عند احتياجنا إليها!!

ملاحظة: شخصيا، التفكير في سرعة البرنامج غير مفيدة وهذا لأن الكثير من البرامج لا تتطلب سرعة! مثلا برنامج عقاري عملاق لن يحتاج إلى التفكير في هذه التفاصيل! لأن فرق الثواني لن يحس بها المستخدم!! إلا إذا كان البرنامج مهمته حساب رياضيات معقدة أو خادم يخدم مئات المستخدمين مثلا!!

تجربة رائعة!!

#4

أولاً شكراً لك لتنسيق الكود

ثانياً : إني اخالفك الرأي فإن التفكير في سرعة البرنامج هي من أول مهام المبرمج الناجح,لأن البرنامج سرعان ما يتطور و تزداد متطلبات المستخدمين , عندها تصبح الثواني التي لم تكن تعني لك شيئاُ أثناء التنفيذ موضوعاً جوهرياً بالنسبة لك.

#5

لسلام عليكم،

في كثير من الكتب والمراجع تجد عبارة تقول للمبرمج: "إذا كنت تريد لبرنامجك أداءً قوياً وسريعاً فليس لك بديل عن C++، وإذا كنت تبحث عن الاستقلالية عن نظام التشغيل حتى يعمل برنامجك الذي كتبته مرة واحدة على مختلف الأنظمة فالحل الوحيد هو Java". ووجوب اهتمام المبرمج بسرعة الأداء فيكون من ناحية كتابة الخوارزمية الأسرع في التنفيذ (أي في التعقيد الزمني للخورازمية) وليس في سرعة أداء لغة البرمجة. وهذا هو المبرمج المحترف.

وكون البحث الذي أجريته أثبت لك أن Java ليست مستقلة عن نظام التشغيل، فهذا أمر طبيعي كما ذكر الأخ أبو مازن. فلا يمكن أن تكون لغة جافا مستقلة عن نظام التشغيل بأي شكل من الأشكال بحسب وجهة نظرك (باستخدام النياسب أو بدونها)، ولكن الاستقلالية هي للمبرمج وليست للغة (أيضاً كما ذكر الأخ أبو مازن)، فالمبرمج يكتب شيفرة مستقلة عن النظام لأنه لا يحتاج لإعادة كتابتها من أجل كل نظام مختلف.

تحياتي لكم ...

هذا الموضوع مغلق.

مواضيع مشابهة