<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>multithread &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/multithread/</link>
	<description>Feed of posts on WordPress.com tagged "multithread"</description>
	<pubDate>Mon, 28 Dec 2009 12:38:33 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Parte 1 - Thread? O que é isso? Pra que isso? ]]></title>
<link>http://metamorfuzzy.wordpress.com/2009/10/13/parte-1-thread-o-que-e-isso-pra-que-isso/</link>
<pubDate>Tue, 13 Oct 2009 00:25:48 +0000</pubDate>
<dc:creator>metamorfuzzy</dc:creator>
<guid>http://metamorfuzzy.wordpress.com/2009/10/13/parte-1-thread-o-que-e-isso-pra-que-isso/</guid>
<description><![CDATA[Criar threads e usa-las não é uma tarefa complicada, porém o uso deste recurso introduz algumas difi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Criar <em>threads</em> e usa-las <strong>não é uma tarefa complicada</strong>, porém o uso deste recurso introduz algumas dificuldades que não são enfrentadas pelo programador quando o mesmo utiliza a programação seqüencial.</p>
<p>Dizer que um programa é <em>multithread</em> é o mesmo que dizer que este programa possui vários pontos de execução, sendo um ponto para cada <em>thread</em>. Pra facilitar a compreensão é como se existisse um processador para cada <em>thread</em>, assim, ao criar uma <em>thread</em> você pode imaginar-se instanciando um novo processador para fazer o trabalho que você está dando para aquela <em>thread</em> fazer.</p>
<p>Eu acredito muito que o leitor não possui um super computador com dezenas de processadores, sendo assim, melhor manter o exemplo acima apenas para fins de compreensão do que realmente é uma <em>thread</em> ok?(Isso foi apenas um momento auto-ajuda, afinal de contas auto-ajuda vende muito mais que livros de informática. <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> )</p>
<p>Na verdade o Sistema Operacional com seu algoritmo de escalonamento de processos, pede ao processador para fazer uma pequena parte do trabalho de cada vez e trocando de uma <em>thread</em> para outra e de um processo para outro tão rapidamente que temos a impressão de possuir vários processadores. Na verdade todo o processamento é feito em cima das <em>threads</em>, todo processo tem pelo menos uma <em>thread</em>, sendo assim,quando digo que o processador troca de um processo para outro é simplesmente para lembrar-lhe que temos <em>threads</em> de outros processos sendo executados o tempo todo.</p>
<p>Podemos dizer que os processos com suas respectivas <em>threads</em> concorrem ao processador e por essa e por outras o termo concorrência é tão usado ao se falar de <em>threads</em>.</p>
<p><strong>Mas por que usar <em>multithreads</em>? Para que concorrência?</strong></p>
<p>Caso você tenha um micro ou um servidor multiprocessado em mente já deve ter surgido imediatamente em sua cabeça a idéia de usar os recursos dos vários processadores que possui, afinal de contas para que tanto processador se não para aproveitar os mesmos.</p>
<p>Outra coisa seria utilizar as <em>threads</em> para trabalhar com dispositivos lentos (comparados ao nosso nobre processador) como impressoras, rede, discos e outros. Assim nossa <em>thread</em> vai fazer esse serviço de esperar o retorno dos nossos dispositivos “lesmas” enquanto nosso programa principal faz coisas mais importantes.</p>
<p>Agora, uma coisa é certa, a razão é sempre dos usuários. Mediante isso por que não pensar neles? Então por que deixar aquela tela travada para que o coitado fique abrindo o gerenciador de tarefas e matando o malvado processo que teima em travar todas as vezes que ele pede a geração de um determinado relatório ou uma consulta um pouco mais rebuscada, ou coisa do tipo? Neste caso a thread seria uma aliada. Ela iria trabalhar na consulta e a interface gráfica não seria substituída por uma tela branca travada e sem vida.</p>
<p>Um caso um pouco mais raro para a grande maioria dos desenvolvedores seria o uso na construção de uma aplicação distribuída. Imagine-se criando o seu próprio IIS, receber as requisições do usuário e então criar uma <em>thread</em> para cada requisição e deixa-la atende-lo. Obs.: Dei um exemplo extremamente simplista do trabalho do IIS, meramente ilustrativo.</p>
<p>Então é mais ou menos isso, sei que fui simplista, mas&#8230; pra que complicar? O objetivo foi entender o conceito. Logo virei com a segunda parte dessa conversa sobre <em>threads</em>. Como cria-las e controla-las.</p>
<p>Comentários e críticas são muito bem vindas.</p>
<p>Abraços!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[別讓你的多核心只是裝飾品！Intel TBB 2.2 發布]]></title>
<link>http://chia0418.wordpress.com/2009/08/18/%e5%88%a5%e8%ae%93%e4%bd%a0%e7%9a%84%e5%a4%9a%e6%a0%b8%e5%bf%83%e5%8f%aa%e6%98%af%e8%a3%9d%e9%a3%be%e5%93%81%ef%bc%81intel-tbb-2-2-%e7%99%bc%e5%b8%83/</link>
<pubDate>Tue, 18 Aug 2009 15:09:04 +0000</pubDate>
<dc:creator>chia0418</dc:creator>
<guid>http://chia0418.wordpress.com/2009/08/18/%e5%88%a5%e8%ae%93%e4%bd%a0%e7%9a%84%e5%a4%9a%e6%a0%b8%e5%bf%83%e5%8f%aa%e6%98%af%e8%a3%9d%e9%a3%be%e5%93%81%ef%bc%81intel-tbb-2-2-%e7%99%bc%e5%b8%83/</guid>
<description><![CDATA[Intel® Threading Building Blocks (TBB) 是一個協助將演算法平行化處理的函式庫。利用多核心可以同時處理多執行緒的優點，TBB自動將資料拆成數塊，分別由各個執行緒執行]]></description>
<content:encoded><![CDATA[Intel® Threading Building Blocks (TBB) 是一個協助將演算法平行化處理的函式庫。利用多核心可以同時處理多執行緒的優點，TBB自動將資料拆成數塊，分別由各個執行緒執行]]></content:encoded>
</item>
<item>
<title><![CDATA[Java: Memulai Pemrograman Multithreading]]></title>
<link>http://komputasi.wordpress.com/2009/08/14/java-memulai-pemrograman-multithreading/</link>
<pubDate>Fri, 14 Aug 2009 00:37:39 +0000</pubDate>
<dc:creator>Husni Ilyas</dc:creator>
<guid>http://komputasi.wordpress.com/2009/08/14/java-memulai-pemrograman-multithreading/</guid>
<description><![CDATA[Multithreading mengacu kepada dua atau lebih task (tugas, thread) yang berjalan (sedang dieksekusi) ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Multithreading mengacu kepada dua atau lebih task (tugas, thread) yang berjalan (sedang dieksekusi) di dalam satu program. Thread merupakan suatu path eksekusi independen di dalam program. Banyak thread dapat nerjalan secara konkuren (berbarengan) di dalam program. Setiap thread di dalam Java dibuat dan dikendalikan oleh kelas java.lang.Thread. Suatu program Java dapat mempunyai banyak thread, dan thread-thread ini dapat berjalan secara bersamaan, secara asinkron atau sinkron.</p>
<p>Multithreading mempunyai beberapa keuntungan, dibandingkan multiprocessing, di antaranya:</p>
<ul>
<li> Thread bersifat lightweight, sedangkan proses lebih berat. Perlu diketahui bahwa proses adalah program yang sedang berada di memory atau processor, sedang dieksekusi. Thread dapat diartikan sebagai anak dari proses.</li>
<li> Thread-thread berbagi pakai ruang alamat yang sama dan karena itu dapat berbagi pakai data dan kode (instruksi)</li>
<li> Context switching antar thread biasanya lebih murah daripada antar proses.</li>
<li> Biaya komunikasi antar thread relatif lebih rendah daripada komunikasi antar proses.</li>
<li> Thread memungkinkan task-task berbeda dikerjakan secara konkuren.</li>
</ul>
<p><strong>Note</strong>: Penjelasan lebih detail mengenai konsep thread dan proses dapat dibaca pada buku teks mengenai Sistem Operasi, di antaranya karya Stallings dan Tanenbaum yang banyak digunakan di Universitas di Dunia.</p>
<p>Kelas Thread merupakan turunan dari kelas Object. Kelas Object sendiri mempunyai metode notify(), notifyAll() dan wait(), sedangkan kelas Thread menyediakan metode sleep() dan yield(). Metode-metode ini akan sering digunakan dalam pengelolaan aplikasi banyak thread.</p>
<p><!--more--></p>
<p><strong>Pembuatan Thread </strong></p>
<p>Terdapat 2 (dua) cara membuat thread di dalam Java:</p>
<ul>
<li> Mengimplementasikan interface Runnable (java.lang.Runnable)</li>
<li> Menurunkan (extend) kelas Thread (java.lang.Thread)</li>
</ul>
<p><strong>Mengimplementasikan Interface Runnable </strong></p>
<p>Bentuk dasar (<em>signature</em>) dari <em>interface </em>Runnable adalah</p>
<pre class="brush: java;">
public interface Runnable {
    void run();
}
</pre>
<p>Pada pendekatan ini, kita harus membuat sebuah kelas yang implementasi interface Runnable menggunakan kata kunci <strong>implements Runnable</strong>. Kemudian dibuat instansiasi berupa suatu obyek dari kelas itu. Kita perlu meng-override metode <strong>run() </strong>di dalam kelas itu, satu-satunya metode yang perlu diimplementasikan. Metode run() mengandung logika dari thread yang dibangun.</p>
<p>Prosedur pembuatan thread berdasarkan pendekatan interface  Runnable adalah sebagai berikut:</p>
<ol>
<li> Sebuah kelas meng-implements interface Runnable, menyediakan metode run() di dalamnya yang akan dieksekusi oleh thread nantinya. Obyek dari kelas ini merupakan obyek Runnable.</li>
<li> Obyek dari kelas Thread dibuat dengan melewatkan obyek Runnable sebagai argumen ke konstruktur Thread. Obyek Thread sekarang mempunyai suatu obyek Runnable yang mengimplementasikan metode run().</li>
<li> Metode start() pada obyek Thread yang dibuat sebelumnya dipanggil. Metode start() tersebut kembali segera setelah suatu thread dilahirkan (berhasil dibuat).</li>
<li> Thread berakhir ketika metode run() berakhir, baik dengan penyelesaian normal atau dengan melempar suatu eksepsi tidak tertangkap (<em>uncaught exception</em>).</li>
</ol>
<p>Di bawah ini adalah sebuah program yang mengilustrasikan  pembuatan thread menggunakan interfaca Runnable, bukan meng-extend kelas Thread. Suatu thread dimulai ketika kita memanggil metode start() pada obyek yang dibuat.</p>
<pre class="brush: java;">

class RunnableThread implements Runnable {

	Thread runner;

	public RunnableThread() {	}

	public RunnableThread(String threadName) {
		runner = new Thread(this, threadName); // (1) Buat thread baru.
		System.out.println(runner.getName());
		runner.start(); // (2) Memulai eksekusi thread tersebut.
	}

	public void run() {
		//Tampilkan info tentang thread ini
		System.out.println(Thread.currentThread());
	}
}

public class RunnableExample {

	public static void main(String[] args) {
		Thread thread1 = new Thread(new RunnableThread(), &quot;thread1&quot;);
		Thread thread2 = new Thread(new RunnableThread(), &quot;thread2&quot;);
		RunnableThread thread3 = new RunnableThread(&quot;thread3&quot;);

		//Memulai eksekusi thread.
		thread1.start();
		thread2.start();
		try {
			//delay selama satu detik (1000 ms).
			Thread.currentThread().sleep(1000);
		} catch (InterruptedException e) {   }

		//Tampilkan info tentang thread main (utama).
		System.out.println(Thread.currentThread());
	}
}
</pre>
<p>Keluaran dari Program di atas dapat berupa:</p>
<p>thread3<br />
Thread[thread1,5,main]<br />
Thread[thread2,5,main]<br />
Thread[thread3,5,main]<br />
Thread[main,5,main]private</p>
<p>Pendekatan ini harus digunakan jika kelas yang menginstansiasi obyek thread diperlukan (sebagai parent) untuk membuat kelas-kelas lain yang merupakan keturunannya. Pada kasus demikian, kita tidak boleh menurunkan kelas Thread, harus mengimplementasikan Runnable.</p>
<p><strong>Meng-Extend Kelas Thread</strong></p>
<p>Prosedur pembuatan thread melalui pendekatan penurunan kelas Thread adalah sebagai berikut:</p>
<ol>
<li>Membuat sebuah sub-kelas turunan dari kelas Thread, kemudian meng-override metode run() dari kelas Thread dan di dalamnya didefinisikan beberapa kode yang dieksekusi oleh thread.</li>
<li>Sub-kelas ini dapat memanggil suatu konstruktur Thread secara eksplisit untuk menginisialisasi thread, menggunakan metode super().</li>
<li>Metode start() yang telah diturunkan (secara otomatis) dari kelas Thread dipanggil agar thread segera berjalan.</li>
</ol>
<p>Berikut ini adalah sebuah program yang mengilustrasikan pembuatan thread dengan meng-extend kelas Thread sebagai ganti mengimplementasikan interface Runnable. Metode start() digunakanuntuk mengeksekusi obyek thread yang dibuat.</p>
<pre class="brush: java;">

class XThread extends Thread {

	XThread() {  }

	XThread(String threadName) {
		super(threadName); // Memulai thread.
		System.out.println(this);
		start();
	}

	public void run() {
		//Tampilkan info tentang thread ini
		System.out.println(Thread.currentThread().getName());
	}
}

public class ThreadExample {

	public static void main(String[] args) {
		Thread thread1 = new Thread(new XThread(), &quot;thread1&quot;);
		Thread thread2 = new Thread(new XThread(), &quot;thread2&quot;);

		// 2 thread diberikan nama default
		Thread thread3 = new XThread();
		Thread thread4 = new XThread();
		Thread thread5 = new XThread(&quot;thread5&quot;);

		//Memulai eksekusi thread
		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
		try {
	//Metode sleep() dipanggil pada thred main (utama), delay 1 detik.
			Thread.currentThread().sleep(1000);
		} catch (InterruptedException e) {	}

		//Tampilkan info tentang thread main
		System.out.println(Thread.currentThread());
	}
}
</pre>
<p>Keluaran yang diperoleh dapat berupa:</p>
<p>Thread[thread5,5,main]<br />
thread1<br />
thread5<br />
thread2<br />
Thread-3<br />
Thread-2<br />
Thread[main,5,main]</p>
<p>Pada saat membuat thread, ada dua alasan mengapa kita mengimplementasikan interface Runnable, bukan meng-extend kelas Thread:</p>
<ul>
<li> Menurunkan kelas Thread berarti bahwa subclass tidak dapat diturunkan menjadi kelas lain lagi, sedangkan suatu kelas yang mengimplementasikan interface Runnable mempunyai opsi ini.</li>
<li> Suatu kelas mungkin hanya diinginkan runnable, karena itu menurunkan Thread secara penuh merupakan pemborosan.</li>
</ul>
<p>Contoh dari kelas anonim berikut memperlihatkan bagaimana membuat sebuah thread dan langsung menjalankannya:</p>
<pre class="brush: java;">

( new Thread() {
   public void run() {
      for(;;) System.out.println(”Stop the world!”);
   }
}
).start();
</pre>
<p>Masih banyak fitur lain di Java yang dapat digunakan untuk mengelola thread. Insya Allah coba dibahas pada tulisan berikutnya.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[localtime is not thread safe]]></title>
<link>http://arkaitzj.wordpress.com/2009/07/30/localtime-is-not-thread-safe/</link>
<pubDate>Thu, 30 Jul 2009 08:56:48 +0000</pubDate>
<dc:creator>Arkaitz Jimenez</dc:creator>
<guid>http://arkaitzj.wordpress.com/2009/07/30/localtime-is-not-thread-safe/</guid>
<description><![CDATA[Thats right, current glibc&#8217;s implementation of localtime function is not thread-safe, instead ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Thats right, current glibc&#8217;s implementation of localtime function is not thread-safe, instead we have localtime_r available which offers the same functionality but it is reentrant.<br />
Here is why</p>
<li><b><i>glibc/time/localtime.c</i></b></li>
<pre>
struct tm _tmbuf;
/* Return the `struct tm' representation of *T in local time,
   using *TP to store the result.  */
struct tm *
__localtime_r (t, tp)
     const time_t *t;
     struct tm *tp;
{
  return __tz_convert (t, 1, tp);
}
weak_alias (__localtime_r, localtime_r)

/* Return the `struct tm' representation of *T in local time.  */
struct tm *
localtime (t)
     const time_t *t;
{
  return __tz_convert (t, 1, &#38;_tmbuf);
}
libc_hidden_def (localtime)
</pre>
<p><!--more--></p>
<p>The localtime representation is returned in a chunk of memory than in the case of <em>localtime_r</em> is given by the user but in the case of the standard <em>localtime</em> <strong>every call returns the result in the same memory chunk</strong>, currently it uses the file scoped variable <strong>_tmbuf</strong> in localtime compilation unit.<br />
So simultaneous calls to the <em>localtime</em> will produce non-desired results in every real concurrency scenario.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Skyboard Software - Current Version: Build 77:3453 - Added SEO Automation process to the mix.  :)  whoo hooo]]></title>
<link>http://skyboardsoftware.wordpress.com/2009/07/26/skyboard-software-current-version-build-773453-added-seo-automation-process-to-the-mix-whoo-hooo/</link>
<pubDate>Mon, 27 Jul 2009 04:11:10 +0000</pubDate>
<dc:creator>burndata</dc:creator>
<guid>http://skyboardsoftware.wordpress.com/2009/07/26/skyboard-software-current-version-build-773453-added-seo-automation-process-to-the-mix-whoo-hooo/</guid>
<description><![CDATA[thank god for DOM&#8230;. what a breeze.  you know.. Nice Seo Recipe: 3 Cups of Database 1 Cup of DO]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>thank god for DOM&#8230;. what a breeze.  you know..</p>
<p>Nice Seo Recipe:</p>
<p>3 Cups of Database</p>
<p>1 Cup of DOM</p>
<p>1 dash of magic</p>
<p>1 heaping bin of skyboard software</p>
<p>but really I just added some nice search engine submission routines (auto web form with database backend to populate fields)&#8230;.</p>
<p>Also added a nice keyword field to the SB board master table&#8230;. also had to add the proper interfaces to the skyboard board cache index&#8230;..</p>
<p>Still I need to get some supersampling happening&#8230;. if you know you know&#8230;</p>
<p>whoo hoo</p>
<p>Lenn Dolling<br />
Skyboard Software</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[the dining philosophers]]></title>
<link>http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/</link>
<pubDate>Mon, 29 Jun 2009 08:32:13 +0000</pubDate>
<dc:creator>karanglayung</dc:creator>
<guid>http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/</guid>
<description><![CDATA[the dining philosophers   road-traffic deadlock  Di dalam ilmu komputer, apabila dijumpai beberapa p]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><table border="0" bgcolor="#ffff00">
<tbody>
<tr>
<td bgcolor="#ffcc00">
<div class="mceTemp">
<div class="mceTemp">
<div id="attachment_535" class="wp-caption alignnone" style="width: 228px"><a rel="attachment wp-att-535" href="http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/dining_philosophers_00/"><img class="size-full wp-image-535" title="dining_philosophers_00" src="http://karanglayung.wordpress.com/files/2009/06/dining_philosophers_00.jpg" alt="the dining philosophers" width="218" height="188" /></a><p class="wp-caption-text">the dining philosophers</p></div>
</div>
</div>
</td>
<td bgcolor="#ffcc00"> </p>
<div id="attachment_540" class="wp-caption alignnone" style="width: 342px"><a rel="attachment wp-att-540" href="http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/citydeadlock_thumb/"><img class="size-full wp-image-540" title="citydeadlock_thumb" src="http://karanglayung.wordpress.com/files/2009/06/citydeadlock_thumb.jpg" alt="road-traffic deadlock" width="332" height="193" /></a><p class="wp-caption-text">road-traffic deadlock</p></div>
<p><a rel="attachment wp-att-514" href="http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/dining_philosophers_02/"></a></td>
</tr>
</tbody>
</table>
<p> Di dalam ilmu komputer, apabila dijumpai beberapa proses yang berjalan secara mandiri tetapi menggunakan sumber daya (<em>resources</em>) yang sama, akan terjadi kemungkinan keadaan saling menunggu secara timbal-balik (jika hanya melibatkan 2 pemakai/proses), atau secara &#8220;melingkar&#8221; (jika melibatkan lebih dari 2 pemakai/proses), yang disebut sebagai kebuntuan (<em><strong>deadlock),</strong></em> misalnya di dalam suatu proses <strong><em>multi-threading.</em></strong></p>
<p>Contoh lainnya dari keadaan kebuntuan (<em>deadlock</em>) dalam peristiwa sehari-hari: adalah kebuntuan arus lalu-lintas di suatu persimpangan jalan, di mana setiap kendaraan berada dalam posisi saling-menghalangi kendaraan lainnya, dan pada saat yang sama saling menunggu kendaraan lainnya untuk bergerak maju dulu seperti juga ditunjukkan pada gambar di atas. Sebuah Applets kartun sederhana yang memperagakan sebuah deadlock dapat dilihat <a href="http://mcs109.bu.edu/site/?p=deadlock">di sini </a>.</p>
<p>Keadaan &#8217;saling-tunggu-secara melingkar&#8217; di atas digambarkan seperti keadaan di mana 5 orang <em>filsuf</em> duduk melingkar dalam suatu jamuan makan (<em>dinner</em>) di sebuah meja bundar di restoran China. Untuk bisa memakan makanan China, setiap orang memerlukan sepasang (2 buah) supit (<em>chopstick</em>), jadi akan diperlukan 10 batang supit utk. kelima filsuf tersebut.  Masalahnya, saat itu restoran sedang penuh pelanggan hingga persediaan supit yg ada sampai tidak mencukupi.</p>
<p>Maka, sang pelayan restoran punya gagasan: &#8220;<em>ah, bukankah para filsuf ini punya kebiasaan makan sambil sesekali berhenti dan melamun (berfikir), jadi toh mereka bisa menggunakan supit secara bergantian.</em>&#8221; Maka di meja para filsuf tersebut hanya disediakan 5 batang supit yang ditaruh berselang-seling di antara kelima piring/mangkuk makanan mereka seperti terlihat pada gambar di atas.</p>
<p>Apa yang diharapkan si pelayan memang bisa saja terwujud, kalau saja para filsuf ini bisa &#8220;berkoordinasi&#8221;, kalau salah seorang sedang makan, filsuf yang duduk persis di sebelahnya harus berhenti makan dan berfikir, dan sebaliknya. Dengan demikian, setiap filsuf yang sedang mendapat &#8220;giliran&#8221; makan akan bisa menggunakan kedua batang supit yang ditaruh di sebelah kanan dan kirinya. Tetapi karena koordinasi seperti ini tidak ada, ada saat-saat di mana kelima filsuf secara serentak ingin makan, dan masing-masing (maksimum) hanya kebagian 1 supit, misalnya yang di sebelah kanan-nya, maka mereka hanya mengangkat sebatang supit itu dengan tangan kanannya, sambil menunggu supit di sebelah kiri mereka *selesai dipakai* oleh tetangganya, ini akan menyebabkan ke 5 filsuf tersebut saling menunggu selama-lamanya &#8230; <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<table border="0" bgcolor="#ffff00">
<tbody>
<tr>
<td bgcolor="#ffcc00"> </p>
<p><div id="attachment_543" class="wp-caption alignnone" style="width: 451px"><a rel="attachment wp-att-543" href="http://karanglayung.wordpress.com/2009/06/29/the-dinning-philosophers/dining_philosophers_02-2/"><img class="size-full wp-image-543" title="dining_philosophers_02" src="http://karanglayung.wordpress.com/files/2009/06/dining_philosophers_021.jpg" alt="the dining psilosophers versi plesetan :)" width="441" height="278" /></a><p class="wp-caption-text">the dining psilosophers versi plesetan <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p></div></td>
</tr>
</tbody>
</table>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[[Delphi] Berkenalan dengan Thread]]></title>
<link>http://programminglearning.wordpress.com/2009/05/26/delphi-berkenalan-dengan-thread/</link>
<pubDate>Tue, 26 May 2009 16:33:11 +0000</pubDate>
<dc:creator>Tigor Manurung</dc:creator>
<guid>http://programminglearning.wordpress.com/2009/05/26/delphi-berkenalan-dengan-thread/</guid>
<description><![CDATA[Di Tutorial ini saya akan akan mengajak temen-temen untuk berkenalan dengan thread, sebelum memulai ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Di Tutorial ini saya akan akan mengajak temen-temen untuk berkenalan dengan thread, sebelum memulai pengkodeannya terlebih dahulu kita harus mengetahui sebenarnya apa itu thread, pengertian ini dikutip dari <a href="http://id.wikipedia.org/wiki/Thread" target="_blank">http://wikipedia.org</a> :<!--more--></p>
<blockquote><p><strong>Ulir</strong> atau <em><strong>thread</strong></em> (singkatan dari &#8220;<em>thread of execution</em>&#8220;) dalam <a title="Ilmu komputer" href="http://id.wikipedia.org/wiki/Ilmu_komputer">ilmu komputer</a>, diartikan sebagai sekumpulan perintah (instruksi) yang dapat dilaksanakan (dieksekusi) secara sejajar dengan ulir lainnya, dengan menggunakan cara <em>time slice</em> (ketika satu <a title="CPU" href="http://id.wikipedia.org/wiki/CPU">CPU</a> melakukan perpindahan antara satu ulir ke ulir lainnya) atau <em>multiprocess</em> (ketika ulir-ulir tersebut dilaksanakan oleh CPU yang berbeda dalam satu sistem). Ulir sebenarnya mirip dengan <a title="Proses" href="http://id.wikipedia.org/wiki/Proses">proses</a>, tapi cara berbagi sumber daya antara proses dengan ulir sangat berbeda. <em>Multiplethread</em> dapat dilaksanakan secara sejajar pada sistem komputer. Secara umum <em>multithreading</em> melakukan <em>time-slicing</em> (sama dengan <em>time-division</em> multipleks), di mana sebuah CPU bekerja pada ulir yang berbeda, di mana suatu kasus ditangani tidak sepenuhnya secara serempak, untuk CPU tunggal pada dasarnya benar-benar melakukan sebuah pekerjaan pada satu waktu. Teknik penggantian (<em>switching</em>) ini memungkinkan CPU seolah-olah bekerja secara serempak.</p></blockquote>
<p>nah, apabila telah paham akan pengertian sebuah thread rasanya tidak komplit apabila saya tidak mencontohkan / mengimplementasikannya. sebelumnya bagi temen-temen yang belum mengerti tentang pembuatan suatu class karena ini akan mengeksploitasi kemampuan pembuatan class silahkan belajar dulu cara membuat class di <a href="http://programminglearning.wordpress.com/2009/05/02/bermain-main-dengan-class/" target="_self">sini</a>. baik pertama kita buat rancangan form sebagai berikut :</p>
<p><a rel="attachment wp-att-288" href="http://programminglearning.wordpress.com/2009/05/26/delphi-berkenalan-dengan-thread/thread_design/"><img class="aligncenter size-full wp-image-288" title="Design Form" src="http://programminglearning.wordpress.com/files/2009/05/thread_design.jpg" alt="Design Form" width="450" height="273" /></a></p>
<p>isi dari form tersebut hanya 5 panel,5 button dan 5 progressbar dan khusus untuk button dan progressbar namanya adalah untuk button : btn1,btn2,btn3,dst dan progressbar : pb1,pb2,pb3,dst.</p>
<p>Pertama-tama kita buat terlebih dahulu suatu class TThreadButton yang akan kita gunakan untuk mendefinisikan antara button dengan thread, class TThreadButton merupakan class turunan dari TButton, kita letakkan di atas class TForm itu sendiri, pendeklarasiannya adalah sebagai berikut :</p>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">

TThreadButton = class(TButton)
aThread: TThread;
end;
</pre>
</pre>
<p>kemudian selanjutnya kita buat suatu thread yang kali ini saya beri nama TthCounter yang pendeklarasiannya adalah sebagai berikut :</p>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">

TthCounter = class(TThread)
 private
  FMax,FCounter: integer;
  FCurr: Extended;
  FOwnerButton: TThreadButton;
  FProgressBar: TProgressBar;
  procedure SetOwnerButton(const aButton: TThreadButton);
  procedure SetProgressBar(const aProgressbar: TProgressBar);
  procedure StepProgress;
  { Private declarations }
 protected
  procedure Execute; override;
 public
  constructor Create(CreateSuspended: boolean);
  property ProgressBar: TProgressBar read FProgressBar write SetProgressBar;
  property OwnerButton: TThreadButton read FOwnerButton write SetOwnerButton;
end;
</pre>
</pre>
<p>dan sintak terusan untuk class TthCounter adalah sebagai berikut :</p>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">

constructor TthCounter.Create(CreateSuspended: boolean);
begin
 inherited;
 FCounter                    := 0; //step awal kita beri nilai 0
 FMax                        := MAXINT; //maksimal step adalah nilai dari maksimal tipe integer
 FreeOnTerminate             := True; //lepaskan thread apabila terdeteksi ada pengakhiran aplikasi
end;

procedure TthCounter.Execute;
begin
 ProgressBar.Position          := 0;
 while ProgressBar.Position &amp;#38;amp;amp;amp;lt; 100 do
  begin
   StepProgress; //gunakan synchronize untuk pemanggilan suatu method
                //yang berhubungan dengan objek

   inc(FCounter,50000); //tambahkan nilai variabel FCounter sebanyak 50000
  end;

 OwnerButton.Caption := '&amp;#38;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;Start';
 OwnerButton.aThread := nil;
end;

procedure TthCounter.SetOwnerButton(const aButton: TThreadButton);
begin
 FOwnerButton := aButton;
end;

procedure TthCounter.SetProgressBar(const aProgressbar: TProgressBar);
begin
 FProgressBar := aProgressbar;
end;

procedure TthCounter.StepProgress;
begin
 FCurr                 := (FCounter / FMax); //posisi sekarang
 ProgressBar.Position  := Round(FCurr * 100); //masukkan posisi progressbar
end;
</pre>
</pre>
<p>Selanjutnya pada Form kita buat prosedur yang nantinya berfungsi untuk memanggil thread tersebut, deklarasinya adalah sebagai berikut :</p>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">

procedure ClickButton(aProgressBar: TProgressBar ; Sender: TObject);
</pre>
</pre>
<pre>dan sintak penerusnya adalah</pre>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">

procedure TfrmMain.ClickButton(aProgressBar: TProgressBar ; Sender: TObject);
var
 aButton: TThreadButton;
 aThread: TthCounter;
begin
 aButton := TThreadButton(Sender); //definiskan aButton sesuai dengan pengirim perintah
 if not Assigned(aButton.aThread) then  //jika thread milik aButton belum terisi maka
  begin
   aThread                     := TthCounter.Create(True); //buat thread baru
   aProgressBar.DoubleBuffered := True; //supaya progressbar tidak flicker
   aThread.ProgressBar         := aProgressBar; //definisikan progressbar
   aButton.aThread             := aThread; //beri nilai thread milik aButton dgn thread deklarasi
   aThread.OwnerButton         := aButton; //isi properti thread
   aThread.Resume; //jalankan thread
   aButton.Caption             := '&amp;#38;amp;amp;amp;amp;Pause'; //ubah caption tombol
  end
else  //kondisi bahwa thread milik aButton telah terisi
 begin
  if aButton.aThread.Suspended then //apabila posisi suspend maka
   begin
    aButton.aThread.Resume; //jalankan ulang thread
    aButton.Caption := '&amp;#38;amp;amp;amp;amp;Pause'; //ubah caption
   end
  else  //apabila thread sedang berjalan maka
   begin
    aButton.aThread.Suspend; //suspend thread
    aButton.Caption := '&amp;#38;amp;amp;amp;amp;Resume';//ubah caption
   end;
end;
end;
</pre>
</pre>
<p>Nah untuk event tiap-tiap button adalah sebagai berikut :</p>
<ul>
<li><strong>OnClick Btn1</strong></li>
</ul>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">
ClickButton(pb1,btn1);
</pre>
</pre>
<ul>
<li><strong>OnClick Btn2</strong></li>
</ul>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">
ClickButton(pb2,btn2);
</pre>
</pre>
<ul>
<li><strong>OnClick Btn3</strong></li>
</ul>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">
ClickButton(pb3,btn3);
</pre>
</pre>
<ul>
<li><strong>OnClick Btn4</strong></li>
</ul>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">
ClickButton(pb4,btn4);
</pre>
</pre>
<ul>
<li><strong>OnClick Btn5<br />
</strong></li>
</ul>
<pre>
</pre>
<pre>
<pre class="brush: delphi;">
ClickButton(pb5,btn5);
</pre>
</pre>
<p>Nah apabila telah mengikuti langkah &#8211; langkah seperti di atas kita jalankan aplikasi yang telah kita buat dan apabila benar maka hasilnya adalah sebagai berikut :</p>
<p><a rel="attachment wp-att-305" href="http://programminglearning.wordpress.com/2009/05/26/delphi-berkenalan-dengan-thread/thread_preview/"><img class="aligncenter size-full wp-image-305" title="Hasil Compile" src="http://programminglearning.wordpress.com/files/2009/05/thread_preview.jpg" alt="Hasil Compile" width="450" height="267" /></a></p>
<p>Bagi temen-temen yang belum jelas atau malah belum jalan, dapat mendownload project lengkapnya <a href="http://www.4shared.com/file/121763552/328e85ee/Thread.html" target="_blank">disini</a></p>
<p>Demikian tutorial ini, semoga dapat memberikan wawasan baru bagi temen-temen semua.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Orbit Downloader 2.8.10]]></title>
<link>http://filemirrors.wordpress.com/2009/05/05/orbit-downloader-2810/</link>
<pubDate>Tue, 05 May 2009 09:09:04 +0000</pubDate>
<dc:creator>filemirrors</dc:creator>
<guid>http://filemirrors.wordpress.com/2009/05/05/orbit-downloader-2810/</guid>
<description><![CDATA[Orbit Downloader is the leader of download manager revolution, devoted to new generation web (web2.0]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><img src="http://filemirrors.wordpress.com/files/2009/04/orbit-downloader.jpg" alt="orbit-downloader" title="orbit-downloader" width="400" height="400" class="alignnone size-full wp-image-59" /></p>
<p>Orbit Downloader is the leader of download manager revolution, devoted to new generation web (web2.0) downloading, such as video/music/streaming media from Myspace, YouTube, Imeem, Pandora, Rapidshare, support RTMP. And to make general downloading easier and faster. In general, Orbit Downloader is based on P2P technology. It has a smart download logic accelerator that features intelligent dynamic file segmentation. And Orbit Downloader has advanced robust multithread download algorithm implemented with high quality. It can speed up to 500% faster with great acceleration. Orbit Downloader is written with efficiency in mind, it typically uses less than 3MB of memory and 3% of cpu when downloading. Additionally, the installation package is just about 2MB. Orbit downloader Support HTTPS and HTTP POST method. Orbit downloader can make your downloads from file-sharing service websites including RapidShare much faster, safer and more stable. Orbit Downloader supports IE, FireFox, Maxthon and Opera internet browsers. You can easily download files with a browser click from any remote server via HTTP, HTTPS, FTP, RTSP and MMS. You can set Orbit Downloader to use a proxy server. Orbit Downloader can work well with HTTP, HTTPS and SOCKS5 protocols. Orbit Downloader can resume broken downloads. So you needn&#8217;t start the downloading process from the very beginning after casual interruption. You can resume unfinished download from the moment when it was interrupted. The latest Orbit Downloader version 2.8.10 has improved functionality with the new Internet Explorer 8 (IE8) web browser from Microsoft and some resolved problems with the GetIt button.</p>
<p>- <a href="http://uploading.com/files/XBT0VOXW/OrbitDownloaderSetup-2.8.10.exe.html" target="_blank"><b>Download Orbit Downloader 2.8.10</b></a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ogre的多執行緒體驗@Vista]]></title>
<link>http://chia0418.wordpress.com/2009/03/04/ogre%e7%9a%84%e5%a4%9a%e5%9f%b7%e8%a1%8c%e7%b7%92%e9%ab%94%e9%a9%97vista/</link>
<pubDate>Wed, 04 Mar 2009 15:55:43 +0000</pubDate>
<dc:creator>chia0418</dc:creator>
<guid>http://chia0418.wordpress.com/2009/03/04/ogre%e7%9a%84%e5%a4%9a%e5%9f%b7%e8%a1%8c%e7%b7%92%e9%ab%94%e9%a9%97vista/</guid>
<description><![CDATA[在Ogre的多執行緒體驗中，介紹了如何開啟Ogre對多執行緒的支援 但是在使用的時候，程式總是莫名的crash在某個地方，連個例外都不給 trace的結果，每次都是在建立某個特定的ManualObje]]></description>
<content:encoded><![CDATA[在Ogre的多執行緒體驗中，介紹了如何開啟Ogre對多執行緒的支援 但是在使用的時候，程式總是莫名的crash在某個地方，連個例外都不給 trace的結果，每次都是在建立某個特定的ManualObje]]></content:encoded>
</item>
<item>
<title><![CDATA[Ogre的多執行緒體驗]]></title>
<link>http://chia0418.wordpress.com/2009/02/26/ogre%e7%9a%84%e5%a4%9a%e5%9f%b7%e8%a1%8c%e7%b7%92%e9%ab%94%e9%a9%97/</link>
<pubDate>Thu, 26 Feb 2009 11:19:59 +0000</pubDate>
<dc:creator>chia0418</dc:creator>
<guid>http://chia0418.wordpress.com/2009/02/26/ogre%e7%9a%84%e5%a4%9a%e5%9f%b7%e8%a1%8c%e7%b7%92%e9%ab%94%e9%a9%97/</guid>
<description><![CDATA[個人一直很欣賞multithread的程式寫作方式，可以在跑程式的時候，多出幾個人執行緒分別負責不同的事情。當然，多點人手自然就要多花精神去管理，天下沒有白吃的午餐。隨著CPU朝向多核心發展，多執行緒]]></description>
<content:encoded><![CDATA[個人一直很欣賞multithread的程式寫作方式，可以在跑程式的時候，多出幾個人執行緒分別負責不同的事情。當然，多點人手自然就要多花精神去管理，天下沒有白吃的午餐。隨著CPU朝向多核心發展，多執行緒]]></content:encoded>
</item>
<item>
<title><![CDATA[Application Scaling on CMT and Multicore Systems]]></title>
<link>http://mediageeks.wordpress.com/2009/02/13/application-scaling-on-cmt-and-multicore-systems/</link>
<pubDate>Fri, 13 Feb 2009 09:19:07 +0000</pubDate>
<dc:creator>jcarlossanchez</dc:creator>
<guid>http://mediageeks.wordpress.com/2009/02/13/application-scaling-on-cmt-and-multicore-systems/</guid>
<description><![CDATA[http://developers.sun.com/solaris/articles/scale_cmt.html?cid=e7978]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>http://developers.sun.com/solaris/articles/scale_cmt.html?cid=e7978</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Powershell to Move Multiple Mailboxes in Multithread ]]></title>
<link>http://smtpport25.wordpress.com/2009/02/09/powershell-to-move-multiple-mailboxes-in-multithread/</link>
<pubDate>Mon, 09 Feb 2009 15:20:14 +0000</pubDate>
<dc:creator>Krishna</dc:creator>
<guid>http://smtpport25.wordpress.com/2009/02/09/powershell-to-move-multiple-mailboxes-in-multithread/</guid>
<description><![CDATA[This is a Beautiful piece of code which helps in moving the Multiple mailboxes in Multithread. Sourc]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This is a Beautiful piece of code which helps in moving the Multiple mailboxes in Multithread. </p>
<p>Sourcefilepath contact the text file with the list of alias names or email address of the users to move.<br />
TargetDatabase should have the path of the destination store where mailstore to be moved.<br />
Maxthreads 8 will move 8 users at a time, you can increase this count based on the performace of your machine.<br />
-BadItemsLimit is if mailbox which is moved has some corrupted item then move-mailbox wil skip the corruption upto 30 items. If this corsses then specific mailbox will not be moved, but it will continue to move rest of the mailbox. </p>
<p>$TargetDatabase = &#8220;Path to the destination Store&#8221;<br />
$k = Get-Content &#8220;SourceFilepath&#8221;<br />
$k&#124; Get-Mailbox &#124; Move-Mailbox -BadItemLimit &#8216;30&#8242; -TargetDatabase $TargetDatabase -maxthreads 8 -Confirm: $false </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Multi-core programming and design: tips and tricks]]></title>
<link>http://vodoom.wordpress.com/2008/12/16/multi-core-programming-and-design-tips-and-tricks/</link>
<pubDate>Tue, 16 Dec 2008 00:24:50 +0000</pubDate>
<dc:creator>ppi</dc:creator>
<guid>http://vodoom.wordpress.com/2008/12/16/multi-core-programming-and-design-tips-and-tricks/</guid>
<description><![CDATA[Multi-core programming is the new trend in software programming, the new big thing that will earn th]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Multi-core" target="_blank">Multi-core</a> programming is the new trend in software programming, the new big thing that will earn the big consulting companies the big bucks.</p>
<p>Don&#8217;t get me wrong: I am not saying it&#8217;s a fad or something like that, I am just saying that it&#8217;s not something new at all, <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Symmetric_multiprocessing" target="_blank">SMP</a> machines exists for many<br />
years now.<br />
I started working with this kind of machine in 1997, a <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Silicon_Graphics" target="_blank">SGI</a> machine with 16 processors. Old stuff that becomes new stuff, again &#8230;<br />
Since then, when working for banking or financial companies, this has always been the motto: let&#8217;s do it faster. Add more ram, more cpus, more disks.<br />
And, yes please, use them as efficiently as possible: I paid the big bucks for the hardware, the software <strong>must</strong> use it  (Nowadays the companies willing to spend the most time and money on multi-core programming will probably be the gaming companies).</p>
<p>So &#8230; We have more computing power now and we want to use it efficiently, we want to keep these cpus busy.<br />
Of course this is not easy, in order to get a faster program, having more than one cpu does not make automatically any of your applications faster. One must choose the right technology in order to achieve the most efficiency out of these new <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Multi-core" target="_blank">multi-core</a> cpus.</p>
<p><a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Multithreading" target="_blank">Multi-threading</a> is the most common chosen technology to try to use the multiple cores available on your $600 desktop or +10,000$ on your brand new server.<br />
But multi-threading is not the <strong>only</strong> technology that does exist to maximize your computing efficiency nor it is the <strong>right</strong> technology to solve every problem: <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Multiprocessing" target="_blank">multi-processing</a> is also a good choice under certain circumstances.</p>
<p>So you want to optimize or develop a new program that would scale when in presence of multiple cores/cpus, here are the steps I follow when trying it:</p>
<p><strong>First things first:</strong><strong> check the operating system the program is supposed to run on.</strong></p>
<ul>
<li>why: not all operating systems are created equal when dealing with multiple cpus. Even if your preferred OS claims to support multiple cores it may not be able to use them efficiently i.e. where are the  <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Giant_lock" target="_blank">GL</a> contention point in your OS ?</li>
</ul>
<ul>
<li>example: if your new application is a networking app and you think that multiple cpus will make it faster you should check if your OS implements a <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/Giant_lock" target="_blank">BGL</a> around networking APIs.</li>
</ul>
<ul>
<li>conclusion: check your OS internals regarding areas where you expect multiple core to speed-up your application. usually I use SOLARIS and Linux, I tend to avoid MAC OSX and other UNIX like <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/HP-UX" target="_blank">HP-UX</a> and <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/IBM_AIX" target="_blank">IBM AIX</a>. I do not use windows boxes, hence I cannot make any comment on them.</li>
</ul>
<p>I will not speak of correct time-sharing and scheduling in presence of multiple cores since all these OS have good support for those.</p>
<p><strong>choose between multi-threading and multi-processing.</strong><br />
As I previously said, multi-threading is not always the right choice for your multi-core applications. This always a shock to people I talk with, since for them multi-threading is the only answer to multi-core programming.<br />
So here are a description of situations where multiple processes may be a better choice than multiple threads in a single process:</p>
<ul>
<li>robustness, multiple threads share the same address space, hence if one generates a fault, the whole application may crash. Multi-thread applications do not run in complete isolation, so if certain threads of your program MUST stay alive no matter what can happen to the other threads, multi-threading may be a bad choice. If restarting the program upon failure is not an issue, you can safely ignore the robustness requirement.</li>
<li>integrity, when designing multiple processes application, each process has its own address space so if one process goes crazy, it cannot corrupt the other processes data, it can only corrupt the shared data between processes. On the other hand, if a thread goes crazy it can corrupt the other threads data since there is no memory protection between threads. This is particularly true when a parent spawns a child process, the child process does whatever computation it needs, and then terminate. If any corruption occurs when doing the computation, it just goes away when the child dies: a new process is spawn to handle a new computation without being affected the previous child fault. There is no such safety net with threads. Corruption made by one thread is program wide, regardless of its lifetime.</li>
</ul>
<p>Now a description of when a multi-threading application is more desirable than a multi-process one:</p>
<ul>
<li>CPU bound applications, video/sound/images processing, numerical simulations (finite elements, molecules interactions)</li>
<li>high bandwidth message passing, this is when multiple threads exchanges messages for processing at very high rate i.e. the processing done on the various messages is very lightweight.</li>
<li>cache friendly code, this is related to CPU bound applications</li>
<li>model driven, multiple threads just make your coding easier: 1 request to be processed by 1 thread, like network connections etc. (yep this is naive e.g. see <a class="wp-caption-dd" href="http://www.kegel.com/c10k.html" target="_blank">C10K</a> problem,<a class="wp-caption-dd" href="http://pl.atyp.us/content/tech/servers.html" target="_blank"> high performance server design</a>)</li>
</ul>
<p>Still not decided between multi-threaded and multi-process application ?</p>
<p>Measure the time necessary for the computations, if this amount of time is really small i.e. lightweight computation, compare it to the time taken to increment/decrement a semaphore between 2 processes. If they are in the same order of magnitude, you probably be more satisfied with multi-threading<br />
Otherwise, multi-processing is a very viable choice. Multi-processing is a good choice when the computation takes an order of magnitude more time than the time spent exchanging data.</p>
<p><strong>reduce contention</strong><br />
See <a class="wp-caption-dd" href="http://www.ddj.com//architect/208200273" target="_blank">ddj article</a> &#8211; that&#8217;s what will kill your application (regardless of multi-threading or multi-processing).</p>
<ul>
<li>reduce code size that is protected by mutexes/semaphores i.e. a whole numerical simulation between two threads is a bad idea</li>
</ul>
<ul>
<li>reduce the necessity for locking, fastest way of sharing data between two threads ? No sharing at all !!! if you are in a master/slave processing model, try to have the master make a copy of the data to be protected by the mutex/semaphore and feed the copy to the various slaves. Copying the shared data can be way much cheaper than competing for a lock (especially when the number of threads increase).</li>
</ul>
<ul>
<li>try to use dirty-reads, do you really need to know the exact value of a shared data i.e. the value of a counter.<br />
Example: you have to remove items from a cache when the item is expired. The item expires at 11:00, the current timestamp value is protected by a mutex. Locking can be avoided, since reading 11:00 or 11:01 (it has been updated by another thread while reading it) does not really mater: as soon as the timestamp is greater than 11:00 deletion can be performed. Your counter/timestamp is quite big ? See if <a class="wp-caption-dd" href="http://portal.acm.org/citation.cfm?id=128736" target="_blank">Lamport concurrent reading and writing of clocks algorithm</a> applies to you (it&#8217;s simple and effective).</li>
<li>do not forget that memory is not cheap to access, check some <a class="wp-caption-dd" href="http://www.nwcpp.org/Downloads/2007/Machine_Architecture_-_NWCPP.pdf" target="_blank">machine architecture docs</a> to educate yourself on these low levels issues</li>
</ul>
<p><strong>If dealing with a CPU bound application, beware of trashing</strong>: that <a class="wp-caption-dd" href="http://docs.sun.com/source/819-0501/7_tuning.html" target="_blank">beast</a> will decrease your performance while maintaining your various cores busy<br />
<strong></strong></p>
<p><strong>If dealing with a CPU bound application, maximize the use of your cpu architecture</strong>. This is quite a last resort action, but it can be <strong>very</strong> effective.<br />
For example, I had to a given computation on a <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/PowerPC" target="_blank">powerpc</a> processor. The computation involved multiple floating point operations. The <a class="wp-caption-dd" href="http://en.wikipedia.org/wiki/PowerPC" target="_blank">powerpc</a> is a beautiful beast, you have multiple floating point engines when doing the calculations (in my case 4 if I remember correctly).</p>
<p>The trick was to make the compiler produce code that use all of them.</p>
<p><strong>The  following code and discussion are not about loop unrolling</strong> (yes it is closely related), here we try to avoid stalling the cpu pipeline by using the multiples floating point units.</p>
<p>original code (and simplified code):</p>
<pre>float* a = new float[1000];
float* b = new float[1000];
float* c = new float[1000];
// most cpu time was spent in there...
for ( int i = 0; i &#60; 1000; ++i )
{
    c[i] = 0;
    for ( int j = 0; j &#60; 1000; ++j )
    {
        c[i] += a[j] * b[j];
    }
}</pre>
<p>updated loop:</p>
<pre>for ( int i = 0; i &#60; 1000; ++i )
{
    float partial_sum = 0;
    for (int j = 0; j &#60; 1000; j += 4)
    {
        // load data into the various processor registers
        float a1 = a[j];
        float a2 = a[j+1];
        float a3 = a[j+2];
        float a4 = a[j+3];
        float b1 = b[j];
        float b2 = b[j+1];
        float b3 = b[j+2];
        float b4 = b[j+3];

        // compute all sums in isolation, so they can be mapped
        // independantly to the various floating point engines
        float s1 = a1 * b1; // FPU engine 1
        float s2 = a2 * b2; // FPU engine 2
        float s3 = a3 * b3; // FPU engine 3
        float s4 = a4 * b4; // FPU engine 4

        s1 += s2; // FPU engine 1
        s3 += s4; // FPU engine 2

        partial_sum += s1 + s3; // FPU engine 1
    }
    c[i] = partial_sum;
}</pre>
<p>This is longer but much more efficient and related to multi-threading: you are using the concurrency offered by your processor at the operation level: s1, s2, s3, s4 are computed in parallel, then s1 and s3 are computed in parallel again. This is very good, and most of the time, neglected source of concurrency for your programs.</p>
<p>The previous code, the updated loop, will probably be faster even on classic x86 chips with only 1 FPU, reason being that placing data in registers (explicitly) will be faster than retrieving the data from the cache.</p>
<p>Forget about the fact that this is a powerpc processor and there are multiple FPU engines etc.<br />
What we <strong>really</strong> did here, was to provide the compiler with <strong>lot</strong> of context, on how the operation should be done and handled. After that the compiler can work on the optimizations, register allocations etc. Always provide your compiler a maximum of context on the computation to be performed.</p>
<p><strong>You are not alone, seek advices and help</strong><br />
The conclusion to this post is: think twice before writing a multi-core application, check the os, your design and implementation with these previous notes before writing any line of code. Get some help from old schools SMP programmers, get them to review the design and get them to give you some tips. Multi-core programming is hard, really hard.</p>
<p>That&#8217;s all folks, for now. I&#8217;ll probably make a few other posts about multi-core programming, I have yet to decide the material to write on <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Enjoy and share.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Stimare accuratamente la potenza di una wireless (parte due)]]></title>
<link>http://thedarshan.wordpress.com/2008/11/21/stimare-accuratamente-la-potenza-di-una-wireless-parte-due/</link>
<pubDate>Fri, 21 Nov 2008 16:10:32 +0000</pubDate>
<dc:creator>thedarshan</dc:creator>
<guid>http://thedarshan.wordpress.com/2008/11/21/stimare-accuratamente-la-potenza-di-una-wireless-parte-due/</guid>
<description><![CDATA[Ho fatto una modifica allo script del post precedente facendo in modo che lo script controlli tutte ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Ho fatto una modifica allo script del post <a href="http://thedarshan.wordpress.com/2008/01/08/stimare-accuratamente-la-potenza-di-una-wireless/">precedente</a> facendo in modo che lo script controlli tutte le wireless contemporaneamente.</p>
<p>Ho inoltre aggiunto un paramentro fortuna che in maniera assolutamente empirica calcola quanto sia possibile connettersi a quella wireless.</p>
<p>I valori vanno da 0 a 100, per valori superiori a 50 la connessione dovrebbe essere stabile<br />
<!--more--></p>
<pre class="brush: ruby;">
#!/usr/bin/ruby
@versione=&quot;1.1.1&quot;
@monitors=Hash.new(&quot;None&quot;)

def spazia(valore,n=20)
    return valore.to_s if n&lt;valore.to_s.size
    return valore.to_s+&quot; &quot;*(n-valore.to_s.size)
end

def tokenize(stream)
	token=Hash.new(&quot;None&quot;)
	stream.each(&quot;Cell&quot;){&amp;#124;cella&amp;#124;
		nome=cella.scan(/ESSID.*/).to_s[7...-1]
		token[nome]=cella
	}
	return token
end

def battery()
	begin
	responso=[]
	`cat /proc/acpi/battery/BAT1/state`.each{&amp;#124;riga&amp;#124; responso&lt;&lt;riga}
	attuale=responso[4].scan(/:.*/).to_s[7..-1].to_f
	massima=responso[3].scan(/:.*/).to_s[7..-1].to_f
	percento=(100*attuale/massima).to_i
	return &quot;Batteria in carica: #{attuale}mAh&quot; if not responso[2].scan(&quot;discharging&quot;).size&gt;0
	return &quot;Nella batteria rimangono &quot;+responso[4].scan(/:.*/).to_s[7..-1]+&quot; pari al #{percento}%&quot;
	rescue =&gt; azz
		return &quot;Informazioni ACPI non disponibili&quot;
	end
end

def fortuna(p,l)
	f= (p+13) / (1.0+(l-50)/6000)
	return 100 if f&gt;100
	return f
end

class Monitor
    def initialize(essid)
        @alpha=1.0/8
        @n=0
        @beacon=0
        @power=0
        @delay=2
        @same=0#Scarto assoluto medio esponenziale
        @oldpower=0
        @essid=essid
    end
    def estrai(celle)
            @cella=celle[@essid]
            beacon=celle[@essid].scan(/beacon.*/).to_s[8..-7].to_i
            power=celle[@essid].scan(/uality.*/).to_s[7..-6].to_i
            enc=(celle[@essid].split(&quot;Encryption key&quot;)[1])[1..5].tr(&quot;\n&quot;,' ')
            same=(power-@oldpower).abs
            if(@n==0 &amp;#124;&amp;#124; @power+@beacon==0)
                    @beacon=beacon
                    @power=power
            else
                @beacon=(1-3*@alpha)*@beacon+3*@alpha*beacon if power&gt;0
                @power=(1-@alpha)*@power+@alpha*power
                @power=4*@alpha*@power if power==0
                @beacon=@beacon+ 1000*@delay if (beacon==0 &amp;&amp; power==0 &amp;&amp; @beacon&lt;10**6 &amp;&amp; @beacon&gt;0)
            end
            @oldpower=power
            @fortuna=fortuna(@power,@beacon)
            @n=@n+1
            @map={
                &quot;essid&quot; =&gt; @essid ,
                &quot;fortuna&quot; =&gt; @fortuna,
                &quot;mpower&quot; =&gt; @power,
                &quot;mlatence&quot; =&gt; @beacon,
                &quot;beacon&quot;=&gt; beacon,
                &quot;power&quot; =&gt; power,
                &quot;same&quot; =&gt; same.to_i,
                &quot;enc&quot; =&gt; enc
                }
    end

    def compatta()
        puts spazia(@map[&quot;essid&quot;])+spazia(@map[&quot;fortuna&quot;])+spazia(@map[&quot;mpower&quot;])+spazia(@map[&quot;mlatence&quot;])+spazia(@map[&quot;enc&quot;])
    end

    def estesa()
        ora=Time.now.strftime(&quot;%I:%M:%S &quot;)
        puts &quot;\ec \n#{ora} #{battery()}\n&quot;+@cella
	puts &quot;Power    = #{@map[&quot;power&quot;]}&quot;
	puts &quot;Latence  = #{@map[&quot;beacon&quot;]}\n&quot;
	puts &quot;Scarto   = #{@map[&quot;same&quot;]}%\n&quot;
	verso=&quot;up&quot;;verso=&quot;down&quot; if @power&gt;@map[&quot;power&quot;]
	puts &quot;MPower   = #{@power} (#{verso})&quot;;
	verso=&quot;up&quot;;verso=&quot;down&quot; if @beacon&gt;@map[&quot;beacon&quot;]
	puts &quot;MLatence = #{@beacon} (#{verso})&quot;
	puts &quot;Fortuna  = #{@fortuna}&quot;
	puts &quot;Codifica = #{@map[&quot;enc&quot;]}&quot;

    end
end

def thread_main()
    #lista solo le celle attualmente visibili.
    #le statistiche delle celle non visibili non vengono aggiornate.
    responso= `iwlist eth1 s`
    celle=tokenize(responso)
    celle.delete(nil)
        ora=Time.now.strftime(&quot;%I:%M:%S &quot;)
        puts &quot;\ec#{ora} #{battery()}\n\n&quot;
    puts spazia(&quot;ESSID&quot;)+spazia(&quot;Fortuna&quot;)+spazia(&quot;MPower&quot;)+spazia(&quot;MLatence&quot;)+spazia(&quot;Crittografia&quot;)
    celle.each_key{&amp;#124;k&amp;#124;
            @monitors[k]=Monitor.new(k) if @monitors[k]==&quot;None&quot;
            @monitors[k].estrai(celle)
            @monitors[k].compatta()
        }
    puts &quot;\n#{celle.size} celle rilevate&quot;
#    puts @monitors.size
end

thread_main()

esecutore=Thread.new {
    while(true)
#        puts &quot;\ec&quot;
        thread_main()
        sleep 2
    end
}

while(cosa=readline.chomp.upcase)
	if cosa==&quot;Q&quot; then
		Thread.kill(esecutore)
		exit
	end
end
</pre>
<p>ho aggiunto una pagina dedicata a questo script <a href="http://thedarshan.wordpress.com/wscanner/">wscanner</a></pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[multithreading in linux]]></title>
<link>http://parasatria.wordpress.com/2008/10/24/multithreading-in-linux/</link>
<pubDate>Fri, 24 Oct 2008 17:00:19 +0000</pubDate>
<dc:creator>m teguh satria</dc:creator>
<guid>http://parasatria.wordpress.com/2008/10/24/multithreading-in-linux/</guid>
<description><![CDATA[Below is a sample multithreading program based on C language. # include&lt; pthread.h&gt; ... /* par]]></description>
<content:encoded><![CDATA[Below is a sample multithreading program based on C language. # include&lt; pthread.h&gt; ... /* par]]></content:encoded>
</item>
<item>
<title><![CDATA[OpenMP a la Delphi]]></title>
<link>http://pebbie.wordpress.com/2008/09/23/openmp-a-la-delphi/</link>
<pubDate>Tue, 23 Sep 2008 15:54:21 +0000</pubDate>
<dc:creator>pebbie</dc:creator>
<guid>http://pebbie.wordpress.com/2008/09/23/openmp-a-la-delphi/</guid>
<description><![CDATA[Setelah beberapa tulisan[1][2] mengenai OpenMP sebagai bahan kuliah saya jadi penasaran untuk membua]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p align="justify">Setelah beberapa tulisan<sup><a href="http://pebbie.wordpress.com/2008/09/11/openmp-hello-world-a-la-gaiblog/">[1]</a><a href="http://pebbie.wordpress.com/2008/09/18/gravitational-n-body-simulation/">[2]</a></sup> mengenai <a href="http://openmp.org">OpenMP</a> sebagai bahan kuliah saya jadi penasaran untuk membuat <em>tiruannya</em> dengan Delphi berhubung Delphi (saya pakai versi 7) memiliki kelas <em>wrapper</em> untuk menggunakan fasilitas <em>threading</em> di Win32. Sebetulnya Delphi versi 7 sudah lumayan tertinggal (mengingat sekarang sudah ada Delphi 200X)  dalam hal pengembangan (tapi belum tahu juga untuk versi Turbo Delphi) dan untuk varian lainnya adalah FreePascal tetapi alternatif yang diajukan di FreePascal sepertinya tidak kompatibel secara bahasa dengan versi Object Pascal yang digunakan di Delphi 7 jadinya saya masih ragu-ragu. Akhirnya saya teruskan niat untuk mencoba membuat implementasi dari <em>secuil</em> fitur paralelisme OpenMP yaitu parallel for (untuk modifikasi sekumpulan data yang independen).</p>
<p><!--more--><br />
<strong>Pendahuluan</strong></p>
<p align="justify">Langkah pertama adalah membuat algoritma sekuensial yang ingin diparalelkan (dibuat menjadi algoritma yang berjalan secara paralel). Algoritma yang saya pilih adalah seperti tulisan <a href="http://pebbie.wordpress.com/2008/09/11/openmp-hello-world-a-la-gaiblog/">ini</a> yaitu operasi terhadap seluruh elemen <em>array</em> 2 dimensi (misalnya citra) yang hanya melibatkan masing-masing elemen tersebut. Kodenya kira-kira seperti ini (yang dicetak miring adalah operasi elementernya)</p>
<pre class="brush: delphi;">for j := 0 to high(arr) do
    for i := 0 to high(arr[j]) do begin
      arr[j][i] := arr[j][i] + 10; { operasi elementer }
    end;</pre>
<p align="justify">Algoritma ini dipilih karena dianggap cukup sederhana karena jika diimplementasi secara paralel menggunakan <em>thread</em> maka antar <em>thread</em> tidak perlu melakukan komunikasi. Algoritma di atas cukup (bahkan mungkin terlalu) sederhana sehingga tidak bisa dibandingkan dengan algoritma paralel karena untuk membuat algoritma versi paralel ada <em>overhead</em> untuk penciptaan thread, penjadwalan, delegasi tugas, dan pembersihan. Oleh sebab itu yang dijadikan acuan untuk melakukan perbandingan performa adalah algoritma versi paralel yang hanya dikerjakan oleh satu buah <em>thread</em> saja. Waktu eksekusi untuk satu <em>thread</em> ini selanjutnya disebut sebagai t<sub>1</sub> sedangkan waktu eksekusi algoritma versi paralel dengan <strong>n</strong> buah thread akan disebut sebagai t<sub>n</sub> sehingga pemercepatan (peningkatan kecepatan) akan dihitung sebagai perbandingan antara t<sub>1</sub> dengan t<sub>n</sub> (t<sub>1</sub>/t<sub>n</sub>).</p>
<p><strong>Pembuatan kelas <em>Worker Thread</em></strong></p>
<p align="justify">Penggunaan fasilitas <em>threading</em> di Delphi ada dua macam cara. Cara pertama adalah memanfaatkan fungsi-fungsi yang berkaitan dengan <em>thread</em> pada <em>Win32 API</em> dan cara kedua adalah membuat kelas turunan dari kelas <strong>TThread</strong>. Cara kedua dipilih secara subjektif dengan alasan kenyamanan pengelolaan.  Pembuatan kelas turunan TThread dapat memanfaatkan wizard dari delphi dengan menggunakan menu File&#62;New&#62;Other&#62;Thread Object. Fungsi yang ingin dijalankan pada thread ditempatkan sebagai fungsi execute yang menutup(<em>override</em>) implementasi dari kelas TThread. Sifat dari penggunaan kelas turunan TThread adalah objek tersebut akan dibebaskan dari memori setelah fungsi execute selesai dijalankan. Penciptaan dan Pembebasan ini tentunya akan menyebabkan redundansi proses yang tidak terlalu relevan dengan tujuan awal (mempercepat eksekusi). Oleh sebab itu perlu dibuat cara lain sedemikian rupa sehingga objek thread hanya perlu diciptakan sekali sebelum proses utama dilakukan dan hanya perlu sekali dibebaskan dari memori setelah seluruh pekerjaan selesai. Caranya adalah dengan membuat atribut status pada kelas thread dan membuat isi fungsi execute ini melakukan perulangan hingga tercapai status akhir (final state). Untuk itu kita perlu tiga buah keadaan yaitu <em>Running</em>, <em>Idle</em>, dan <em>Done</em>. Pada awalnya keadaan akan diinisialisasi sebagai Idle. Keadaan ini adalah keadaan yang menyatakan objek thread tidak sedang sibuk melakukan pekerjaan sehingga dapat didelegasikan. Jika objek thread sedang sibuk maka keadaannya adalah Running. Kode untuk kelas thread ditunjukkan dalam kode berikut : </p>
<pre class="brush: delphi;">unit Unit2;

interface

uses
  Classes, Windows, SysUtils;

type
  TThreadState = (tsRunning, tsIdle, tsDone);
  TArrElmtModifier = class(TThread)
  private
    { Private declarations }
    FX, FY, FID: integer;
    FState : TThreadState;
  protected
    procedure Execute; override;

    procedure NotifyStart;
    procedure NotifyDone;
  public
    constructor Create(AID:integer);
    procedure Run;
    procedure Done;
    property X : integer read FX write FX;
    property Y : integer read FY write FY;
    property ID : integer read FID write FID;
    property State : TThreadState read FState write FState;
  end;

implementation

uses Unit1;

{ TArrElmtModifier }

constructor TArrElmtModifier.Create(AID:integer);
begin
  inherited Create(false);
  FID := AID;
  X := 0;
  Y := 0;
  State := tsIdle;
  self.FreeOnTerminate := false;
end;

procedure TArrElmtModifier.Done;
begin
  FState := tsDone;
end;

procedure TArrElmtModifier.Execute;
begin
  { Place thread code here }
  while (FState&lt;&gt;tsDone) do begin
    if (FState=tsRunning) then begin
      { Do Thread Task here }
      Form1.arr[Y][X] := Form1.arr[Y][X] + 10;
      NotifyDone;
      { Notify when task done }
    end;
    sleep(1);
  end;
end;

procedure TArrElmtModifier.NotifyDone;
begin
  Form1.AcceptDone(FID);
  State := tsIdle;
end;

procedure TArrElmtModifier.NotifyStart;
begin
  Form1.Memo1.Lines.Add('Thread #'+inttostr(FID)+' started');
end;

procedure TArrElmtModifier.Run;
begin
  State := tsRunning;
end;

end.
</pre>
<p><strong>Implementasi <em>Parallel for</em></strong></p>
<p align="justify">Langkah selanjutnya adalah melakukan penjadwalan untuk alokasi pekerjaan dalam iterasi for agar dikerjakan oleh <em>worker thread</em>. Penyederhanaan (tanpa menggunakan antrian pekerjaan) dilakukan dengan penurunan tiap pekerjaan langsung diturunkan dari pola perulangan yang sama seperti pada algoritma sekuensial sehingga urutan pekerjaan menjadi terurut sesuai dengan eksekusi for. Selanjutnya dilakukan penjadwalan delegasi <em>thread</em> agar tiap <em>thread</em> mendapatkan proporsi beban pekerjaan yang cukup seimbang satu sama lain. Hal ini dilakukan dengan menggunakan antrian berbentuk cincin (ring queue) yang secara sederhana diimplementasi dengan memanfaatkan operator modulo pada struktur data kumpulan objek <em>thread</em> yang menggunakan <em>array</em>. Setelah semua pekerjaan didelegasikan perlu dibuat mekanisme <em>barrier</em> yang akan menunggu konfirmasi penyelesaian dari seluruh thread sebelum thread dibebaskan dari memori. Langkah terakhir adalah menampilkan perubahan. Hasil implementasi pada kode utama ditampilkan sebagai berikut :</p>
<pre class="brush: delphi;">unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Unit2, StdCtrls, Spin;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    SpinEdit1: TSpinEdit;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    SpinEdit2: TSpinEdit;
    Button1: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    nthreads : integer;
    threadflags : array of boolean;
    threads : array of TArrElmtModifier;
    arr : array of array of integer;
    tq : integer;
    procedure Prepare;
    procedure DispatchThreads;
    procedure AcceptDone(idx:integer);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AcceptDone(idx: integer);
begin
  threadflags[idx] := false;
  //memo1.lines.Add('done #'+inttostr(idx));
end;

procedure TForm1.DispatchThreads;
var
  i, j, k : integer;
  busy : boolean;
  tmp : tstrings;
  start, finish : longint;
begin
  Memo1.Lines.Clear;
  start := GetTickCount;

  { ordered scheduling }
  for j := 0 to high(arr) do
    for i := 0 to high(arr[j]) do begin
      { schedule iteration(i,j) }
      busy := true;
      repeat
        k := tq; //GetNextAvailableThread
        //if not threadflags[k] then begin
        if threads[k].State = tsIdle then begin
          threadflags[k] := true;
          //memo1.lines.add(format('dispatch (%d,%d) to thread #%d', [i,j,k]));
          threads[k].X := i;
          threads[k].Y := j;
          threads[k].Run;
          busy := false;
          break;
        end;
        tq := (tq + 1) mod length(threads);
        Application.ProcessMessages;
      until not busy;
    end;

  { barrier, wait until all task finished }
  repeat
    busy := false;
    for k := 0 to high(threads) do begin
      if threadflags[k] then begin
        busy := true;
        break;
      end;
    end;
    Application.ProcessMessages;
  until not busy;
  finish := GetTickCount;
  { clean up threads }
  for i := 0 to high(threads) do
    threads[i].State := tsDone;

  { display changes }
  tmp := TStringlist.Create;
  for j := 0 to high(arr) do begin
    tmp.Clear;
    for i := 0 to high(arr[j]) do begin
      tmp.add(inttostr(arr[j][i]));
    end;
    memo1.Lines.add(tmp.CommaText);
  end;
  Memo1.Lines.Add('Done in '+inttostr(finish-start)+' ms');
  tmp.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  i : integer;
begin
  Prepare;

  nthreads := SpinEdit1.Value;
  setlength(threadflags, nthreads);
  setlength(threads, nthreads);
  for i := 0 to high(threads) do begin
    threadflags[i] := false;
    threads[i] := TArrElmtModifier.Create(i);
  end;

  DispatchThreads;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j, k : integer;
  start, finish : cardinal;
  tmp : TStrings;
begin
  Prepare;
  Memo1.Lines.Clear;
  start := GetTickCount;

  { ordered scheduling }
  for j := 0 to high(arr) do
    for i := 0 to high(arr[j]) do begin
      arr[j][i] := arr[j][i] + 10;
    end;

  finish := GetTickCount;

  { display changes }
  tmp := TStringlist.Create;
  for j := 0 to high(arr) do begin
    tmp.Clear;
    for i := 0 to high(arr[j]) do begin
      tmp.add(inttostr(arr[j][i]));
    end;
    memo1.Lines.add(tmp.CommaText);
  end;
  Memo1.Lines.Add('Done in '+inttostr(finish-start)+' ms');
  tmp.Free;
end;

procedure TForm1.Prepare;
var
  i,n : integer;
begin
  n := SpinEdit2.Value;

  if length(arr)&gt;0 then
    for i := 0 to high(arr) do
      setlength(arr[i], 0);

  setlength(arr, n);
  for i := 0 to high(arr) do
    setlength(arr[i], n);
  tq := 0;
end;

end.</pre>
<div id="attachment_205" class="wp-caption alignnone" style="width: 417px"><a href="http://pebbie.files.wordpress.com/2008/09/thread.png"><img src="http://pebbie.wordpress.com/files/2008/09/thread.png" alt="Tampilan Form (4K PNG)" title="Tampilan Form" width="407" height="502" class="size-full wp-image-205" /></a><p class="wp-caption-text">Tampilan Form (4K PNG)</p></div>
<p><strong>Pengujian</strong></p>
<p align="justify">Untuk menguji perubahan kecepatan pada penggunaan thread digunakan dimensi array 10&#215;10 dan jumlah thread yang diuji antara lain 1 (kontrol), 2, 4, 8, 16 (diabaikan karena asimtotik). Hasil pengukuran ditunjukkan pada gambar berikut.</p>
<div id="attachment_206" class="wp-caption alignnone" style="width: 527px"><a href="http://pebbie.files.wordpress.com/2008/09/speedup.png"><img src="http://pebbie.wordpress.com/files/2008/09/speedup.png" alt="Grafik Speedup (4K PNG)" title="Grafik Speedup" width="517" height="318" class="size-full wp-image-206" /></a><p class="wp-caption-text">Grafik Speedup (4K PNG)</p></div>
<p><strong>Penutup</strong></p>
<p align="justify">Sepertinya bisa dinyatakan berhasil, walaupun sebelumnya saya coba justru bisa dibilang gagal karena penggunaan <em>multithread</em> justru memperlambat (mungkin karena saya menjalankan langsung dari IDE). Selanjutnya mungkin saya akan mencoba bagaimana mengimplementasi pola eksekusi berbentuk pohon, analisis statik independensi antar operasi, dan komunikasi (sinkronisasi) antar thread yang pada tujuan akhirnya adalah mewujudkan salah satu mimpi saya terdahulu yaitu membuat bahasa pemrograman (<em>next generation programming language</em>) paralel (akhirnya tujuan perancangannya bisa lebih spesifik) yang memanfaatkan threading secara implisit (tidak perlu menyatakan pembuatan dan pembersihan objek thread secara eksplisit dalam kode program) dan sebisa mungkin makin meng-eksplisitkan independensi antar data/task pada kode program dan penulisan yang bersih dan nyaman untuk dibaca (yang terakhir agak subjektif dan kurang terdefinisi, hehehe). Perwujudan ini (mungkin) dilakukan dalam beberapa tahap yaitu pengembangan abstract machine (sebagai testbed komputer paralel), interpreter, dan pada akhirnya implementasi compiler dan IDE untuk bahasa baru ini yang untuk sementara saya namakan sebagai &#8216;project pi&#8217; (akhirnya ada juga namanya). </p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[COB: multithread problem]]></title>
<link>http://squareglobus.wordpress.com/2008/07/01/cob-multithread-problem/</link>
<pubDate>Tue, 01 Jul 2008 05:13:12 +0000</pubDate>
<dc:creator>squareglobus</dc:creator>
<guid>http://squareglobus.wordpress.com/2008/07/01/cob-multithread-problem/</guid>
<description><![CDATA[Случай из пратктики. Проблема: Банк решил закрыть день в многопоточном режиме, был сделан SYSTEM.BAC]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Случай из пратктики.</p>
<p><em>Проблема:</em> Банк решил закрыть день в многопоточном режиме, был сделан SYSTEM.BACKUP. Закрытие дня прошло без ошибок. Бизнес начал смотреть резлультаты и выявил пару мелочей, для исправления нужно было откатиться на предыдущий день. Восстановились из бэкапа, внесли нужные изменения и начали закрывать день в многопоточном режиме &#8211; посыпалась масса ошибок, система не могла прочитать какие-то файлы.</p>
<p><em>Решение:</em> пока день закрывали в один поток, BATCH.JOB.CONTROL обходился одним файлом F.JOB.LIST.1, когда первый раз закрыли на 7 потоков, он автоматически создал нужное число F.JOB.LIST.2, F.JOB.LIST.3 и т.д. При этом появились соответствующие записи в VOC. Дальше, мы откатились из бэкапа, т.к. это был SYSTEM.BACKUP, то перетерся только каталог bnk.data и все эти файлы (F.JOB.LIST.2, F.JOB.LIST.3, &#8230;) удалились, а записи в VOC остались. Когда мы заново начали закрывать день в многопоточном режиме, BATCH.JOB.CONTROL обнаружил в VOC, что файлы которые ему нужны, вроде как уже есть, и попытался читать/писать в/из них, что и привело к ошибкам. В конце концов мы почистили в VOC все F.JOB.LIST.n кроме &#8220;1&#8243; и нормально закрыли день.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Evolution of computing power]]></title>
<link>http://cadcraft.wordpress.com/2008/06/13/evolution-of-computing-power/</link>
<pubDate>Fri, 13 Jun 2008 19:51:58 +0000</pubDate>
<dc:creator>Jamal</dc:creator>
<guid>http://cadcraft.wordpress.com/2008/06/13/evolution-of-computing-power/</guid>
<description><![CDATA[A few weeks ago, students &amp; staff at Purdue built their own super computer in just a few hours. ]]></description>
<content:encoded><![CDATA[A few weeks ago, students &amp; staff at Purdue built their own super computer in just a few hours. ]]></content:encoded>
</item>
<item>
<title><![CDATA[4 coeurs, c'est mieux que 2. parfois.]]></title>
<link>http://drgoulu.com/2008/04/19/4-coeurs-cest-mieux-que-2-parfois/</link>
<pubDate>Sat, 19 Apr 2008 20:05:01 +0000</pubDate>
<dc:creator>Dr. Goulu</dc:creator>
<guid>http://drgoulu.com/2008/04/19/4-coeurs-cest-mieux-que-2-parfois/</guid>
<description><![CDATA[A peine s&#8217;est-on habitués à l&#8217;idée d&#8217;avoir des processeurs à double coeur dans nos]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><img class="alignright" style="float:right;margin:3px;" src="http://upload.wikimedia.org/wikipedia/en/thumb/d/da/Cell_Broadband_Engine_Processor.jpg/436px-Cell_Broadband_Engine_Processor.jpg" alt="" width="218" height="300" />A peine s&#8217;est-on habitués à l&#8217;idée d&#8217;avoir des processeurs à double coeur dans nos PC que les quadruple coeurs (<a href="http://www.intel.com/cd/products/services/emea/fra/processors/core2quad/333916.htm" target="_blank">Intel Core 2 Quad</a> ou  <a href="http://multicore.amd.com/us-en/quadcore/" target="_blank">AMD Opteron Quad Core</a>) débarquent dans les PC haut de gamme, et bientôt sur nos bureaux.</p>
<p>Si le double coeur apporte sans conteste un gain de confort (un coeur pour Windows, un autre pour l&#8217;application &#8230;), il faut reconnaitre que très peu d&#8217;applications sont capables de tirer parti du gain de performance qu&#8217;apportent théoriquement deux unités de calcul. Que dire pour quatre ?</p>
<p>L&#8217;article &#8220;<a class="title-link" href="http://www.codinghorror.com/blog/archives/000942.html">Choosing Dual or Quad Core</a>&#8221; de Jeff Atwood donne une réponse simple après de nombreux tests : &#8220;ça dépend&#8221;.</p>
<p>Certaines applications vont presque 2x plus vite avec 4 coeurs qu&#8217;avec 2 : elles sont parfaitement parallélisées, avec des processus très indépendants ne nécessitant que très peu de communication entre eux. <a href="http://www.povray.org/" target="_blank">Pov-Ray</a>, certains benchmarks et des modules de jeux comme le <a href="http://www.anandtech.com/tradeshows/showdoc.aspx?i=2868&#38;p=9">système de particules du moteur Valve Source</a> sont du nombre.</p>
<p>D&#8217;autres logiciels sont moins &#8220;scalables&#8221;, essentiellement parce que les processus doivent s&#8217;échanger des données entre eux, et chaque synchronisation bloque l&#8217;utilisation simultanée des coeurs. Avec 4 coeurs, l&#8217;accélération n&#8217;est &#8220;que&#8221; d&#8217;environ 150%. Dans cette catégorie on trouve par exemple <a href="http://www.microsoft.com/windows/windowsmedia/forpros/encoder/default.mspx"> Windows Media Encoder</a>, <a href="http://www.maxon.net/pages/download/cinebench_e.html">Cinebench</a> et d&#8217;autres programmes de traitement d&#8217;images notamment.</p>
<p>Enfin, il y a tous les programmes qui ne sont pas parallélisés, ou qui n&#8217;ont été codés que pour 2 coeurs. Et il faut bien le reconnaitre, c&#8217;est le cas de la plupart des logiciels actuels.</p>
<p>Reste que la tendance est lancée : les processeurs auront bientôt 4, 8, 16 coeurs (<a href="http://fr.wikipedia.org/wiki/Cell_%28processeur%29" target="_blank">le processeur Cell</a> qui équipe déjà la Playstation III a déjà 1+8 coeurs, on les voit bien sur la photo), et les programmeurs sont en train d&#8217;apprendre à en tirer parti.</p>
<p>Pour l&#8217;instant, un Quad vous apportera donc peu de gain de performance sur des applications interactives. Mais si vous encodez des videos, faites du rendu réaliste ou autres applications fonctionnant pendant des heures en tâche de fond, les 4 coeurs vous apporteront un gain de vitesse tout en laissant la machine disponible pour du travail interactif, ça peut valoir le coup.</p>
<p><em>(article publié aussi <a href="http://microclub.wordpress.com/2008/04/19/4-coeurs-cest-mieux-que-2-parfois/" target="_blank">sur le blog du Microclub</a>)</em></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[POSIX Thread (6) - Mutex]]></title>
<link>http://openandfree.wordpress.com/2007/11/09/posix-thread-6-mutex/</link>
<pubDate>Fri, 09 Nov 2007 03:14:05 +0000</pubDate>
<dc:creator>Hoang Tran</dc:creator>
<guid>http://openandfree.wordpress.com/2007/11/09/posix-thread-6-mutex/</guid>
<description><![CDATA[Chúng ta đã hiểu vấn đề nảy sinh ở chương trình trước. Để giải quyết bài toán xung đột đó chũng ta h]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p class="western" style="margin-bottom:0;" align="justify"><font face="Arial"><font size="2">Chúng ta đã hiểu vấn đề nảy sinh ở chương trình trước. Để giải quyết bài toán xung đột đó chũng ta hãy xem đoạn mã đúng sử dụng mutex:</font></font></p>
<p class="western" style="margin-bottom:0;" align="justify"><strong><font face="Arial"><font size="2">thread3.c</font></font></strong></p>
<pre><font size="2"><tt><strong><font color="#000080">#include</font></strong> <font color="#ff0000">&#60;pthread.h&#62;</font>
<strong><font color="#000080">#include</font></strong> <font color="#ff0000">&#60;stdlib.h&#62;</font>
<strong><font color="#000080">#include</font></strong> <font color="#ff0000">&#60;unistd.h&#62;</font>
<strong><font color="#000080">#include</font></strong> <font color="#ff0000">&#60;stdio.h&#62;</font>
<font color="#009900">int</font> myglobal<font color="#990000">;</font>
pthread_mutex_t mymutex<font color="#990000">=</font>PTHREAD_MUTEX_INITIALIZER<font color="#990000">;</font>
<font color="#009900">void</font> <font color="#990000">*</font><strong><font color="#000000">thread_function</font></strong><font color="#990000">(</font><font color="#009900">void</font> <font color="#990000">*</font>arg<font color="#990000">)</font>
<font color="#ff0000">{</font>
    <font color="#009900">int</font> i<font color="#990000">,</font>j<font color="#990000">;</font>
    <strong><font color="#0000ff">for</font></strong> <font color="#990000">(</font> i<font color="#990000">=</font><font color="#993399">0</font><font color="#990000">;</font> i<font color="#990000">&#60;</font><font color="#993399">20</font><font color="#990000">;</font> i<font color="#990000">++</font> <font color="#990000">)</font> <font color="#ff0000">{</font>
        <strong><font color="#000000">pthread_mutex_lock</font></strong><font color="#990000">(&#38;</font>mymutex<font color="#990000">);</font>
        j<font color="#990000">=</font>myglobal<font color="#990000">;</font>
        j<font color="#990000">=</font>j<font color="#990000">+</font><font color="#993399">1</font><font color="#990000">;</font>
        <strong><font color="#000000">printf</font></strong><font color="#990000">(</font><font color="#ff0000">"."</font><font color="#990000">);</font>
        <strong><font color="#000000">fflush</font></strong><font color="#990000">(</font>stdout<font color="#990000">);</font>
        <strong><font color="#000000">sleep</font></strong><font color="#990000">(</font><font color="#993399">1</font><font color="#990000">);</font>
        myglobal<font color="#990000">=</font>j<font color="#990000">;</font>
        <strong><font color="#000000">pthread_mutex_unlock</font></strong><font color="#990000">(&#38;</font>mymutex<font color="#990000">);</font>
    <font color="#ff0000">}</font>
    <strong><font color="#0000ff">return</font></strong> NULL<font color="#990000">;</font>
<font color="#ff0000">}</font>
<font color="#009900">int</font> <strong><font color="#000000">main</font></strong><font color="#990000">(</font><font color="#009900">void</font><font color="#990000">)</font>
<font color="#ff0000">{</font>
    pthread_t mythread<font color="#990000">;</font>
    <font color="#009900">int</font> i<font color="#990000">;</font>
    <strong><font color="#0000ff">if</font></strong> <font color="#990000">(</font> <strong><font color="#000000">pthread_create</font></strong><font color="#990000">(</font> <font color="#990000">&#38;</font>mythread<font color="#990000">,</font> NULL<font color="#990000">,</font> thread_function<font color="#990000">,</font> NULL<font color="#990000">)</font> <font color="#990000">)</font> <font color="#ff0000">{</font>
        <strong><font color="#000000">printf</font></strong><font color="#990000">(</font><font color="#ff0000">"error creating thread."</font><font color="#990000">);</font>
        <strong><font color="#000000">abort</font></strong><font color="#990000">();</font>
    <font color="#ff0000">}</font>
    <strong><font color="#0000ff">for</font></strong> <font color="#990000">(</font> i<font color="#990000">=</font><font color="#993399">0</font><font color="#990000">;</font> i<font color="#990000">&#60;</font><font color="#993399">20</font><font color="#990000">;</font> i<font color="#990000">++)</font> <font color="#ff0000">{</font>
        <strong><font color="#000000">pthread_mutex_lock</font></strong><font color="#990000">(&#38;</font>mymutex<font color="#990000">);</font>
        myglobal<font color="#990000">=</font>myglobal<font color="#990000">+</font><font color="#993399">1</font><font color="#990000">;</font>
        <strong><font color="#000000">pthread_mutex_unlock</font></strong><font color="#990000">(&#38;</font>mymutex<font color="#990000">);</font>
        <strong><font color="#000000">printf</font></strong><font color="#990000">(</font><font color="#ff0000">"o"</font><font color="#990000">);</font>
        <strong><font color="#000000">fflush</font></strong><font color="#990000">(</font>stdout<font color="#990000">);</font>
        <strong><font color="#000000">sleep</font></strong><font color="#990000">(</font><font color="#993399">1</font><font color="#990000">);</font>
    <font color="#ff0000">}</font>
    <strong><font color="#0000ff">if</font></strong> <font color="#990000">(</font> <strong><font color="#000000">pthread_join </font></strong><font color="#990000">(</font> mythread<font color="#990000">,</font> NULL <font color="#990000">)</font> <font color="#990000">)</font> <font color="#ff0000">{</font>
        <strong><font color="#000000">printf</font></strong><font color="#990000">(</font><font color="#ff0000">"error joining thread."</font><font color="#990000">);</font>
        <strong><font color="#000000">abort</font></strong><font color="#990000">();</font>
    <font color="#ff0000">}</font>
    <strong><font color="#000000">printf</font></strong><font color="#990000">(</font><font color="#ff0000">"</font><font color="#cc33cc">\n</font><font color="#ff0000">myglobal equals %d</font><font color="#cc33cc">\n</font><font color="#ff0000">"</font><font color="#990000">,</font>myglobal<font color="#990000">);</font>
    <strong><font color="#000000">exit</font></strong><font color="#990000">(</font><font color="#993399">0</font><font color="#990000">);</font>
<font color="#ff0000">}</font></tt></font></pre>
<p><!--more--></p>
<p class="western" style="margin-bottom:0;" align="justify"><font face="Arial"><font size="2">Nếu chúng ta so sánh đoạn mã này với đoạn mã trong chương trình thread2.c, chúng ta sẽ thấy có thêm những lời gọi hàm pthread_mutex_lock() và pthread_mutex_unlock(). Những lời gọi hàm này rất cần thiết trong lập trình với thread. Chúng cung cấp cách thức loại trừ lẫn nhau (mutual exclusion) – có nghĩa là khi một thread sử dụng tài nguyên thì thread khác không được sử dụng và phải chờ cho đến khi thread kia giải phóng tài nguyên. Không có hai thread nào có thể cùng có một mutex bị khóa ở một thời điểm. </font></font></p>
<p class="western" style="margin-bottom:0;" align="justify"><font size="2"><font face="Arial">Đó chính là cách thức mutex làm việc. Nếu thread “a” cố gắng khóa một mutex trong khi thread “b” đã khóa cùng mutex đó rồi thì thread “a” sẽ rơi vào trạng thái ngủ (sleep). Ngay khi thread “b” giải phóng mutex (thông qua pthread_mutex_unlock()), thread “a” sẽ có thể khóa mutex (nói một cách khác thì khi đó giá trị của hàm pthread_mutex_lock() sẽ được trả về với mutex bị lock). Ngược lại, nếu thread “c” cố gắng khóa mutex trong khi thread “a” đang nắm giữ nó thì thread “c” cũng sẽ bị rơi vào trạng thái ngủ tạm thời. Tất cả thread mà cùng rơi vào trạng thái ngủ từ lệnh gọi pthread_mutex_lock() vì một khóa mutex đã bị lock sẵn rồi sẽ được đưa vào hàng đợi để truy nhập vào mutex. </font></font></p>
<p class="western" style="margin-bottom:0;" align="justify"><font size="2"><font face="Arial">pthread_mutex_lock() và pthread_mutex_unlock() thường được sử dụng để bảo vệ cấu trúc dữ liệu. Nó đảm bảo rằng chỉ có một thread tại một thời điểm có thể truy nhập vào cấu trúc dữ liệu bằng việc khóa và mở khóa. Bạn cũng có thể đoán ra rằng POSIX threads sẽ cấp một khóa mà không đưa thread đó vào trạng thái ngủ khi nó cố gắng khóa một mutex không bị khóa. </font></font></p>
<p class="western" style="margin-bottom:0;" align="justify"><font size="2"><font face="Arial">Thế nhưng tại sao chúng ta lại phải đưa các thread vào trạng thái sleep? Rõ ràng nó không phải là ưu điểm chính của thread khi mà ta muốn tận dụng khả năng làm việc độc lập và đồng thời của các thread? Đúng vậy. Tuy nhiên thì các chương trình sử dụng thread vẫn thường cần phải sử dụng mutex. </font></font></p>
<p class="western" style="margin-bottom:0;" align="justify"><font face="Arial"><font size="2">Nếu bạn nhìn vào hàm thread_function(), bạn sẽ nhận ra rằng mutex bị khóa vào lúc đầu vòng lặp và giải phóng khi kết thúc. Trong ví dụ này thì mymutex được dùng để bảo vệ giá trị của myglobal. Nếu nhìn cẩn thận hơn, sẽ thấy rằng đoạn mã tăng giá trị của myglobal trong thread_function sẽ copy giá trị myglobal và một biến local và ghi trở lại từ local vào myglobal sau khi tăng (đoạn mã sleep một giây có thể bỏ đi. Chẳng có lý do gì để thread_function phải sleep khi đã sử dụng mutex. Nó được thêm vào để có thể nhìn rõ hơn sự khác biệt).<br />
</font></font></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Опять многопоточность, но теперь в PERL (часть 3-я и последняя)]]></title>
<link>http://nopox.wordpress.com/2007/11/06/multithreading-in-perl-part-3-and-last/</link>
<pubDate>Tue, 06 Nov 2007 23:52:15 +0000</pubDate>
<dc:creator>nopox</dc:creator>
<guid>http://nopox.wordpress.com/2007/11/06/multithreading-in-perl-part-3-and-last/</guid>
<description><![CDATA[Этой статьёй я планирую завершить тему многопоточности в Perl, ибо она меня уже порядком устала . Кс]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Этой статьёй я планирую завершить тему многопоточности в Perl, ибо она меня уже порядком устала <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  . Кстати, предыдущие статьи ни в коем случае не претендуют на полный и подробный мануал, вовсе нет. Это скорее HOWTO, дающее, однако возможность подумать и понять сущность процесса (как мне кажется).</p>
<p>Итак, на повестке дня — <!--more Многопоточность и расшаренные переменные --><br />
Частенько смысл множества потоков состоит в работе над одной большой (или необязательно большой) базой. Возникает резонный вопрос: а как обмениваться информацией между нитями?</p>
<p>Оказывается, очень просто. Достаточно всего лишь подключить специальный модуль <code>threads::shared</code>, и для массивов и скалярных переменных, не являющихся ссылками и объектами, можно указывать модификатор <code>shared</code>, показывающи интерпретатору, что переменная доступна всем тредам. </p>
<p>Как всегда пример:</p>
<pre><code>#!/usr/bin/perl -w

use threads;
use threads::shared;

# Объявляем переменную общей для всех нитей с
# помощью модификатора shared
my $i : shared = 1;

# Альтернативный способ - использование функции share
my $j = 0;
share $j;

threads-&#62;new(\&#38;my_sub)-&#62;join();
threads-&#62;new(\&#38;my_sub)-&#62;join();
threads-&#62;new(\&#38;my_sub)-&#62;join();

sub my_sub()
{
    print "Это вызов #$i. Переменная \$j = $j\n";
    $j++;
    $i++;
}</code></pre>
<p>Результат такого скрипта в консоли выглядит примерно так:</p>
<pre><code>% perl threads.pl
Это вызов #1. Переменная $j = 0
Это вызов #2. Переменная $j = 1
Это вызов #3. Переменная $j = 2</code></pre>
<p>Вроде бы всё понятно и просто и пора уже с многопоточностью заканчивать. В качестве прощания мы с вами напишем скрипт, который будет выдирать прокси с первых пяти страниц небезызвестного ресурса <a href="http://proxylist.sakura.ne.jp/">MPR Proxylist</a> (разумеется, каждая страница отдельным потоком <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). В качестве HTTP-клиента используется библиотека LWP, которая обычно установлена (если не установлена, то пользователи FreeBSD могут устанавливать порт <a href="http://www.freebsd.org/cgi/url.cgi?ports/www/p5-libwww/pkg-descr">www/p5-libwww</a>, а линуксоидам ничем помочь не могу <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ):</p>
<pre><code>
#!/usr/bin/perl -w

use LWP::UserAgent;
use threads;
use threads::shared;

# В этом массиве будут храниться найденные прокси
my @proxies : shared;

# Массив для хранения ссылок на объекты нитей
my @threads;

# Количество страниц (и, разумеется,  нитей <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> )
my $threads = 5;

# Создаём $threads нитей, каждая из которых будет
for (my $i = 0; $i &#60; $threads; $i++) {
    threads-&#62;new(\&#38;find_proxy, $i);
}

# Скрипт будет жить до завершения работы всех нитей
foreach my $thread (@threads) {
    $thread-&#62;join();
}

# Записываем найденные прокси в файл
open PROXIES, '&#62;', 'proxylist.txt';

foreach my $proxy (@proxies) {
    print PROXIES $proxy, "\n";
}

close PROXIES;

# Создание HTTP-клиента на основе LWP (при кажом создании
# у клиента будет разные User-Agent
sub http_factory()
{
    my @agents = ('Mozilla 5.0/Firefox',
                  'Opera 9.02',
                  'Interner Explorer 7',
                  'Safari 3.0/Gecko 31337',
                  'Lynx/FreeBSD 6.0');
    my $client = LWP::UserAgent-&#62;new('agent' =&#62; $agents[rand($#agents)]);
    return $client;
}

# Процедура соединения с донором и парсинг прокси
sub find_proxy
{
    my $page = shift;
    my $url = sprintf('http://proxylist.sakura.ne.jp/index.htm?pages=%s', $page);
    my $client = &#38;http_factory();
    my $response = $client-&#62;get($url) or warn "Can't connect $url: $@\n";

    if ($response-&#62;is_success() &#38;&#38; $response-&#62;content_type() eq 'text/html') {
        my $content = $response-&#62;content();

        while ($content =~ m!
<td>(.*?)</td>

\s*?
<td>([a-z]{2})</td>

!sgi) {
            my $proxy = $1;
            my $country = $2;
            push @proxies, $proxy;
            print "Found $proxy [$country], saving it\n";
        }
    }

    else {
        print "fuck! $@\n";
    }
}</code></pre>
<p>В общем, вроде всё, балуйтесь, детишки. И не забывайте, что это только пример, демонстрирующий мощность многопоточных приложений на Perl <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Удачного дня <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
