the dining-philosopher problem

Upload: khairinaafriani

Post on 14-Jan-2016

19 views

Category:

Documents


0 download

DESCRIPTION

The Dining-philosopher Problem

TRANSCRIPT

The Dining-Philosopher Problem

Dalamilmu komputer, parathe dining-philosopher problemmerupakan contoh masalah yang sering digunakan dalambersamaandesain algoritma untuk menggambarkansinkronisasimasalah dan teknik untuk menyelesaikan mereka.Ini pada awalnya dirumuskan pada tahun 1965 olehEdsger Dijkstrasebagai latihan ujian mahasiswa, disajikan dalam hal komputerbersaing untuk akseske peripheral tape drive.Segera setelah itu,Tony Hoarememberikan masalah formulasi yang sekarang

Ilustrasi the dining-philosopher problemLima filsuf diam duduk di meja di sekitar semangkukspaghetti.Garpu ditempatkan di antara setiap pasangan filsuf yang berdekatan.(Sebuah perumusan masalah alternatif menggunakannasidansumpitbukannya spaghetti dan garpu.)Setiap filsuf harus bergantian berpikir dan makan.Namun, seorang filsuf hanya bisa makan spaghetti ketika ia memiliki garpu kiri dan kanan.Setiap garpu dapat dipegang oleh satu filsuf dan filsuf sehingga dapat menggunakan garpu hanya jika tidak sedang digunakan oleh filsuf lain.Setelah ia selesai makan, ia harus meletakkan kedua garpu sehingga mereka menjadi tersedia untuk orang lain.Seorang filsuf bisa ambil garpu di sebelah kanannya atau satu di sebelah kiri sebagai mereka menjadi tersedia, tetapi tidak bisa mulai makan sebelum mendapatkan keduanya.Makan tidak dibatasi oleh jumlah spaghetti kiri: menganggap persediaan yang tidak terbatas.Masalahnya adalah bagaimana merancang sebuah disiplin perilaku (abersamaanalgoritma) sehingga setiap filsuf tidak akan kelaparan, yaitu selamanya dapat terus bergantian antara makan dan berpikir, dengan asumsi bahwa filsuf apapun tidak dapat mengetahui ketika orang lain mungkin ingin makan atau berpikir.

Masalahnya dirancang untuk menggambarkan masalah menghindarikebuntuan, keadaan sistem di mana tidak ada kemajuan adalah mungkin.Untuk melihat bahwa merancang sebuah solusi yang tepat untuk masalah ini tidak jelas, mempertimbangkan usulan berikut: menginstruksikan setiap filsuf untuk berperilaku sebagai berikut: berpikir sampai garpu kiri tersedia, ketika itu, mengambilnya; berpikir sampai garpu yang tepat tersedia, ketika itu, mengambilnya; ketika kedua garpu dipegang, makan untuk jumlah waktu yang tetap; kemudian, menempatkan garpu kanan bawah; kemudian, meletakkan garpu kiri bawah; ulangi dari awal.Upaya ini pada solusi gagal: memungkinkan sistem untuk mencapai keadaan kebuntuan, di mana tidak ada kemajuan adalah mungkin.Ini adalah keadaan di mana setiap filsuf telah mengambil garpu ke kiri, menunggu garpu ke kanan untuk diletakkan.Dengan petunjuk yang diberikan, keadaan ini dapat dicapai, dan bila sudah tercapai, para filsuf abadi akan menunggu satu sama lain untuk melepaskan garpu.Kelaparan sumber dayamungkin juga terjadi secara independen dari kebuntuan jika seorang filsuf tertentu tidak dapat memperoleh baik garpu karena masalah waktu.Misalnya mungkin ada aturan bahwa para filsuf meletakkan garpu setelah menunggu sepuluh menit untuk garpu lain untuk menjadi tersedia dan menunggu lebih lanjut sepuluh menit sebelum melakukan upaya mereka berikutnya.Skema ini menghilangkan kemungkinan kebuntuan (sistem selalu dapat maju ke negara yang berbeda) tetapi masih menderita masalahlivelock.Jika semua lima filsuf muncul di ruang makan pada waktu yang sama dan masing-masing mengambil garpu kiri pada saat yang sama para filsuf akan menunggu sepuluh menit sampai mereka semua meletakkan garpu mereka turun dan kemudian menunggu lebih lanjut sepuluh menit sebelum mereka semua memilih mereka lagi.Mutual exclusionadalah gagasan inti dari masalah, para filsuf makan membuat skenario generik dan abstrak berguna untuk menjelaskan masalah jenis ini.Kegagalan filsuf ini mungkin mengalami analog dengan kesulitan yang timbul dalam pemrograman komputer nyata ketika beberapa program memerlukan akses eksklusif ke sumber daya bersama.Isu-isu ini dipelajari dalam cabangPemrograman serentak.Masalah asli Dijkstra yang terkait dengan perangkat eksternal seperti tape drive.Namun, kesulitan belajar di makan filsuf masalah muncul jauh lebih sering ketika multiple access proses set data yang diperbarui.Sistem seperti operasi kernel sistem, menggunakan ribuan kunci dan sinkronisasi yang membutuhkan kepatuhan yang ketat untuk metode dan protokol jika masalah seperti kebuntuan, kelaparan, atau korupsi data yang harus dihindari.

Sumber Daya solusi hirarkiSolusi ini untuk masalah ini adalah yang awalnya diusulkan olehDijkstra.Ini memberikan sebuahperintah parsialterhadap sumber daya (garpu, dalam hal ini), dan membangun konvensi bahwa semua sumber daya akan diminta dalam rangka, dan bahwa tidak ada dua sumber yang tidak terkait dengan perintah yang pernah akan digunakan oleh satu unit kerja di waktu yang sama.Di sini, sumber daya (garpu) akan diberi nomor 1 sampai 5 dan masing-masing unit kerja (filsuf) akan selalu mengambil rendah bernomor garpu pertama, dan kemudian garpu lebih tinggi bernomor, dari antara dua garpu ia berencana untuk menggunakan.Urutan bahwa setiap filsuf meletakkan garpu tidak masalah.Dalam hal ini, jika empat dari lima filsuf sekaligus menjemput mereka garpu rendah bernomor, hanya garpu bernomor tertinggi akan tetap di atas meja, sehingga filsuf kelima tidak akan mampu mengambil garpu apapun.Selain itu, hanya satu filsuf akan memiliki akses ke tertinggi bernomor garpu, jadi dia akan bisa makan menggunakan dua garpu.Sementara solusi hirarki sumber daya menghindari deadlock, tidak selalu praktis, terutama ketika daftar sumber daya yang dibutuhkan tidak sepenuhnya diketahui sebelumnya.Sebagai contoh, jika unit kerja memegang sumber daya 3 dan 5 dan kemudian menentukan perlu sumber daya 2, harus melepaskan 5, maka 3 sebelum mengambilnya 2, dan kemudian harus kembali memperoleh 3 dan 5 dalam urutan itu.Program komputer yang mengakses sejumlah besar catatan database tidak akan berjalan secara efisien jika mereka diminta untuk melepaskan semua catatan yang lebih tinggi bernomor sebelum mengakses rekor baru, membuat metode praktis untuk tujuan itu.solusi KonduktorSolusi lain relatif sederhana dicapai dengan memperkenalkan seorang pelayan di meja.Filsuf harus meminta izin sebelum mengambil setiap garpu.Karena pelayan menyadari berapa banyak garpu sedang digunakan, ia mampu menengahi dan mencegah kebuntuan.Ketika empat dari garpu sedang digunakan, filsuf berikutnya untuk meminta seseorang untuk menunggu izin pelayan, yang tidak diberikan sampai garpu telah dirilis.Logikanya ini dibuat sederhana dengan menetapkan bahwa para filsuf selalu mencari untuk mengambil garpu tangan kiri mereka sebelum tangan mereka garpu kanan (atau sebaliknya).Pelayan bertindak sebagaisemaphore, sebuah konsep yang diperkenalkan oleh Dijkstra pada tahun 1965. Untuk menggambarkan bagaimana ini bekerja, pertimbangkan bahwa para filsuf diberi label searah jarum jam dari A sampai E. Jika A dan C makan, empat garpu sedang digunakan.B duduk antara A dan C sehingga memiliki garpu tidak tersedia, sedangkan D dan E memiliki satu garpu terpakai antara mereka.Misalkan D ingin makan.Ketika ia ingin mengambil garpu kelima, kebuntuan menjadi mungkin.Jika dia malah meminta pelayan dan disuruh menunggu, kita bisa yakin bahwa waktu berikutnya dua garpu yang dirilis di sana pasti akan ada setidaknya satu filsuf yang berhasil bisa meminta sepasang garpu.Oleh karena itu kebuntuan tidak bisa terjadi.Chandy / Misra solusiPada tahun 1984,K.Mani Chandydan A. Aggarwal mengusulkan solusi yang berbeda untuk masalah filsuf makan untuk memungkinkan agen sewenang-wenang (bernomorP1, ...,Pn) untuk bersaing untuk jumlah sewenang-wenang sumber daya, tidak seperti solusi Dijkstra.Hal ini juga sepenuhnya didistribusikan dan tidak memerlukan otoritas sentral setelah inisialisasi.Namun, itu melanggar persyaratan bahwa "para filsuf tidak berbicara satu sama lain" (karena pesan permintaan).1. Untuk setiap pasangan filsuf bersaing untuk sumber daya, membuat garpu dan memberikannya kepada filsuf dengan ID yang lebih rendah.Setiap garpu dapat menjadikotorataubersih.Awalnya, semua garpu kotor.2. Ketika filsuf ingin menggunakan seperangkat sumber daya (yaitumakan), ia harus mendapatkan garpu dari tetangganya bersaing.Untuk semua garpu seperti dia tidak punya, dia mengirimkan pesan permintaan.3. Ketika seorang filsuf dengan garpu menerima pesan permintaan, dia terus garpu jika itu bersih, tapi memberikan itu ketika itu kotor.Jika dia mengirimkan garpu di atas, ia membersihkan garpu sebelum melakukannya.4. Setelah seorang filsuf yang selesai makan, semua garpu nya menjadi kotor.Jika filsuf lain sebelumnya telah meminta salah satu garpu, ia membersihkan garpu dan mengirimkannya.Solusi ini juga memungkinkan untuk gelar besar konkurensi, dan akan memecahkan masalah sewenang-wenang besar.Hal ini juga memecahkan masalah kelaparan.Label bersih / kotor bertindak sebagai cara memberikan preferensi yang paling "kelaparan" proses, dan merugikan proses yang baru saja "makan".Satu dapat membandingkan solusi mereka ke salah satu tempat filsuf tidak diperbolehkan untuk makan dua kali berturut-turut tanpa membiarkan orang lain menggunakan garpu di antaranya.Solusi mereka lebih fleksibel daripada itu, tetapi memiliki unsur cenderung ke arah itu.Dalam analisis mereka, mereka berasal sistem tingkat preferensi dari distribusi garpu dan negara bersih / kotor mereka.Mereka menunjukkan bahwa sistem ini dapat menggambarkan grafik asiklik, dan jika demikian, operasi dalam protokol mereka tidak dapat mengubah grafik yang menjadi satu siklik.Hal ini menjamin bahwa deadlock tidak dapat terjadi.Namun, jika sistem diinisialisasi ke keadaan sempurna simetris, seperti semua filsuf memegang garpu sisi kiri mereka, maka grafik adalah siklik di awal, dan solusi mereka tidak dapat mencegah kebuntuan.Memulai sistem sehingga filsuf dengan ID rendah memiliki garpu kotor memastikan grafik awalnya asiklik.

Mengaktifkan C + + pengembang untuk menulis aplikasi yang sangat bersamaan adalah fokus utama dari Visual Studio 2010.Rilis beta meliputi Runtime Concurrency, perpustakaan paralel, dan alat-alat pengembangan yang bertujuan mengatasi beberapa masalah umum mencegah pengembang dari membuka potensi kinerja yang melekat untuk hardware multicore.Khususnya, hal ini termasuk memastikan bahwa pengembang dapat mengidentifikasi dan memanfaatkan peluang untuk concurrency dalam kode mereka, produktif mengelola negara bersama dan efek samping, dan tidak harus khawatir tentang membangun infrastruktur concurrency overhead rendah yang terukur pada saat dijalankan pada varietas perangkat keras.Pada artikel ini, saya akan menunjukkan bagaimana menggunakan Agen Asynchronous baru Perpustakaan dimasukkan sebagai bagian dari Visual C + + 2010 untuk mengelola kesulitan yang dapat timbul dengan negara bersama.Untuk menunjukkan bagaimana ini bekerja, saya akan berjalan melalui sebuah implementasi dari masalah konkurensi klasik: Djikstra yang filsuf Dining.Anda akan melihat bagaimana pemrograman berbasis aktor membangun dari agen dalam kombinasi dengan asynchronous pesan-lewat API dapat digunakan untuk memberikan yang benar dan mudah dimengerti solusi untuk masalah ini yang tidak bergantung langsung pada threading atau sinkronisasi primitif.

Para filsuf DiningBagi mereka yang tidak terbiasa dengan hal itu, Dining Philosophers masalah dimaksudkan untuk menggambarkan kompleksitas pengelolaan negara bersama dalam lingkungan multithreaded.Inilah masalahnya:Pada meja bundar duduk lima filsuf yang bergantian antara berpikir dan makan dari mangkuk besar nasi pada interval acak.Sayangnya bagi para filsuf, hanya ada lima sumpit di meja (lihatGambar 1), dan sebelum para filsuf bisa mulai makan, mereka harus mendapatkan sepasang sumpit.Karena sumpit dibagi antara para filsuf, akses ke sumpit harus dilindungi, tetapi jika perawatan tidak diambil, masalah konkurensi muncul.Terutama, kelaparan (pun intended) melalui kebuntuan dapat terjadi: jika setiap filsuf mengambil sumpit secepat itu tersedia dan menunggu tanpa batas waktu untuk yang lain, akhirnya mereka semua akan berakhir memegang hanya satu sumpit dengan tidak ada kesempatan untuk mendapatkan yang lain.

Gambar 1Para filsuf dan SumpitThe Dining Philosophers Masalah biasanya diwakili dalam kode oleh benang untuk setiap filsuf dan beberapa bentuk negara bersama digunakan untuk mewakili masing-masing sumpit.Solusi mudah untuk masalah ini sering melibatkan memperkenalkan entitas pelayan untuk mengkoordinasikan akses ke sumpit, memperkenalkan kunci memesan heuristik, dan secara manual bekerja dengan threading API, bagian kritis, Semaphore, atau monitor untuk mengelola negara.Kebanyakan pengembang akan setuju bahwa bangunan benar, penguncian trivial dianggap menantang dan rapuh di terbaik.Akibatnya, sebagian besar implementasi dari Dining Philosophers masalah cenderung memiliki rincian pelaksanaan bocor ke dalamnya.Misalnya, para filsuf mungkin menyadari sinkronisasi primitif atau sumpit tetangga mereka.Hal ini menjadi sangat bermasalah jika Anda ingin menggeneralisasi masalah untuk jumlah sewenang-wenang filsuf atau memfokuskan kembali sebuah implementasi pada masalah domain-seperti apa yang setiap filsuf tidak-daripada berfokus pada sinkronisasi dan primitif threading.

Pendekatan Aktor BerbasisMari kita berjalan melalui desain yang dibangun di atas Asynchronous Agen Perpustakaan.Makan filsuf benar-benar hanya memiliki dua bagian cukup sulit: menciptakan thread untuk setiap filsuf untuk berjalan dalam dan mengkoordinasikan akses para filsuf 'untuk sumpit.The Asynchronous Agen Perpustakaan menyediakan model pemrograman berbasis aktor dan pesan asynchronous lewat API, dan Anda akan perlu kedua dalam pelaksanaannya.Dalam Asynchronous Agen Perpustakaan, model agen kelas pola aktor dan menyediakan metode run asynchronous.Saya menggunakan agen untuk setiap filsuf dan memanfaatkan metode dijalankan untuk memenuhi kebutuhan setiap filsuf berjalan di thread sendiri.Bagian kedua dari solusi yang tepat melibatkan mengelola akses bersamaan ke sumpit dan, berbeda dengan solusi tradisional menggunakan Semaphore atau kunci, saya akan menggunakan API lewat pesan dalam Asynchronous Agen Perpustakaan untuk memindahkan sumpit antara tangan para filsuf 'dan tabel.Karena setiap filsuf transisi antara berpikir dan makan, ia mengambil sumpit dan mengembalikan mereka ke meja dengan mengirimkan pesan.Anda akan melihat bahwa selain menyediakan beberapa abstraksi di atas benang dan negara bersama, ini juga akan memungkinkan pelaksanaan hidup lebih fokus pada domain masalah daripada solusi lain memungkinkan.

Solusi Dalam Lima KelasDesain dasar akan menggunakan lima jenis: Sebuah kelas sumpit yang relatif Cukup jelas. Sebuah kelas ChopstickProvider yang akan digunakan untuk memegang sumpit di atas meja dan memberikan mereka kepada para filsuf. Sebuah kelas Filsuf yang bertanggung jawab untuk berpikir dan makan dan menyadari hanya dua ChopstickProviders. Sebuah PhilospherState enum yang dapat berpikir atau makan. Sebuah kelas Tabel yang berisi satu set filsuf dan satu set Sumpit.Tabel bertanggung jawab untuk menata meja dengan menempatkan Chopstick tunggal dalam ChopstickProvider antara setiap Filsuf.Gambar 2menunjukkan hubungan antara kelas.

Gambar 2Kelas Digunakan Dalam Dining Philosophers SolusiMari kita mulai dengan kelas sederhana: Chopstick.Tujuan dari Chopstick adalah untuk hanya ada sebagai sumpit dan dapat mengidentifikasi dirinya.Akibatnya, implementasi adalah kelas sederhana yang memiliki variabel anggota identifier, konstruktor yang menginisialisasi pengenal, dan metode untuk kembali identifier.Chopstick kelas {const std :: string m_Id, publik: Chopstick (std :: string && Id): m_Id (Id) {}; std :: string const getId () {return m_Id;};};Sangat penting untuk dicatat bahwa m_Id bidang identifier adalah variabel anggota const.Saya tidak ingin sumpit untuk memiliki negara sendiri yang bisa berubah secara tidak sengaja oleh thread lain.Juga perhatikan bahwa konstruktor menggunakan referensi r-nilai dalam daftar parameter nya (&&).Ini adalah bahasa baru membangun dalam Visual Studio 2010 yang merupakan bagian dari rancangan C + +0 x standar.Sebuah referensi r-nilai di sini memungkinkan compiler untuk menghindari salinan panggilan konstruktor dan memindahkan Id ke m_Id dalam contoh Chopstick jika Id adalah variabel sementara atau r-nilai.

Pesan Blok Dan PesanChopstickProvider juga mudah.Hal ini dapat dianggap sebagai buffer penyimpanan yang tujuannya adalah untuk menerima Sumpit ketika mereka dikirim ke sana dan untuk menyediakan sumpit ke Philosopher atas permintaan.Berikut adalah tempat pertama di mana saya menggunakan API agen.Saya menggunakan apa yang dikenal sebagai blok pesan untuk ChopstickProvider.Sebuah blok pesan didefinisikan sebagai kelas yang mampu mengirim dan menerima pesan.Lebih khusus lagi, jika Anda dapat mengirim pesan ke pesan blok, blok ini disebut sebagai target dan, jika Anda dapat menerima pesan dari blok pesan, itu disebut sebagai sumber.Dalam contoh ini, saya akan memerlukan ChopstickProvider untuk menjadi sumber dan target karena para filsuf akan baik menerima sumpit dari ChopstickProviders ketika filsuf lapar dan mengirim mereka kembali ke ChopstickProviders ketika filsuf siap untuk berpikir lagi.Berikut ini adalah contoh menempatkan mereka untuk bekerja:/ / Membuat sumpit sumpit sumpit ("sumpit satu"); / / membuat ChopstickProvider untuk menyimpan sumpit ChopstickProvider chopstickBuffer; / / menempatkan sumpit dalam sumpit pemegang Concurrency :: kirim (chopstickBuffer, & sumpit); / / meminta sumpit dari sumpit penyangga sumpit * hasil = Concurrency :: terima (chopstickBuffer);Anda dapat melihat bahwa, setelah menyatakan sumpit dan chopstickBuffer (contoh masih terdefinisi ChopstickProvider), Concurrency :: kirim digunakan untuk menempatkan alamat sumpit ke dalam ChopstickBuffer dan Concurrency :: menerima mengembalikan pointer ke Chopstick dari chopstickBuffer.Concurrency :: kirim adalah metode template yang serentak menempatkan pesan dalam blok pesan.Concurrency :: terima adalah metode template yang mengembalikan pesan dari blok pesan.Concurrency :: menerima blok sampai pesan tersedia di blok pesan.The Asynchronous Agen Perpustakaan juga menyediakan Concurrency :: asend dan Concurrency :: try_receive.Concurrency :: asend asynchronous memunculkan sebuah tugas untuk mengirim pesan tanpa menunggu pengakuan penerimaan.Concurrency :: try_receive adalah panggilan non-blocking yang akan memperoleh pesan jika tersedia.Sekarang mari kita benar-benar mendefinisikan ChopstickProvider.Ingat saya mengatakan itu mudah?Ini adalah typedef:typedef Concurrency :: unbounded_buffer ChopstickProvider;Para agen perpustakaan menyediakan blok pesan disebut unbounded_buffer yang memiliki fungsi yang Anda butuhkan.Sebuah unbounded_buffer adalah kelas template yang baik sumber dan target.Ini menyimpan sejumlah memori terbatas pesan dalam antrian internal.Pesan akan dihapus dari antrian ketika mereka diminta.Anda tidak perlu kualitas tak terbatas dalam pelaksanaan ini Dining Philosophers karena ada sejumlah sumpit yang akan bergerak antara masing-masing pemegang sumpit.Fungsi tombol Anda tertarik dari unbounded_buffer adalah semantik bergerak nya.

Agen Dan Bergabunglah Blok PesanSekarang mari kita lihat menerapkan kelas Filsuf.Ini adalah bagian menarik dari Dining Philosophers masalah, di mana Anda memastikan bahwa setiap filsuf berjalan pada thread sendiri dan bahwa akses ke sumber daya bersama dikoordinasikan dengan tepat.Kelas Philosopher akan menggunakan dua konstruksi tambahan dari Asynchronous Agen Perpustakaan, kelas agen abstrak dan bergabung membangun.Pertama saya akan menjelaskan agen dan bagaimana itu digunakan.Para agen kelas merupakan kelas abstrak yang model apa yang kadang-kadang disebut sebagai pola aktor atau pemrograman berbasis aktor.Agen dimaksudkan untuk digunakan untuk memfasilitasi menghapus dependensi dan negara bersama antara komponen aktif dari aplikasi dengan memiliki agen merangkum negara dan berkomunikasi satu sama lain hanya melalui pesan melewati set kecil antarmuka publik.Ini terdengar lebih rumit dari itu, tapi mudah-mudahan Anda dapat melihat kemiripan dengan kelas Philosopher.Seperti yang saya sebutkan sebelumnya, kelas Filsuf harus berjalan pada thread sendiri.Menerjemahkan ini ke terminologi agen ini berarti perlu menjadi tugas yang aktif, sehingga Filsuf akan berasal dari publik Concurrency :: agen.Kelas Filsuf juga perlu menyadari dua ChopstickProviders (satu untuk masing-masing tangan) dan kemudian menggunakannya untuk transisi berhasil antara berpikir dan makan.Kelas Philosopher belum lengkap, tetapi Anda dapat melihat bagaimana hal ini mulai diterjemahkan ke dalam sinopsis kelas:enum PhilosopherState {Berpikir, Makan}; typedef Concurrency :: unbounded_buffer ChopstickProvider, Filsuf kelas: Concurrency public :: agen {ChopstickProvider * m_LeftChopstickProvider, ChopstickProvider * m_RightChopstickProvider; publik: const std :: string m_Name; const int m_Bites; Filsuf (const std :: string && nama, int gigitan = 500): m_Name (nama), m_Bites (gigitan) {}; ... }Filsuf memiliki pointer ke dua ChopstickProviders, nama, jumlah gigitan atau ternyata Philosopher akan mengambil, dan konstruktor untuk inisialisasi.Apa yang hilang, meskipun, adalah cara untuk menginisialisasi ChopstickProviders di agen.Anda tidak ingin menginisialisasi mereka pada saat konstruksi karena filsuf yang independen dari Sumpit dan ChopstickProviders mereka.Anda bisa membuat metode umum tambahan seperti AssignChopsticks (ChopstickProvider * kiri, ChopstickProvider * kanan), tapi kemudian Anda harus mengambil beberapa perawatan atau kunci-untuk memastikan bahwa metode ini thread aman.Sebaliknya, aku akan membuat antarmuka publik sehingga ChopstickProviders dapat diberikan asynchronous.Saya melakukan ini dengan menambahkan dua variabel anggota unbounded_buffer publik yang lebih dan menggunakan ini untuk mengirim dua filsuf ChopstickProviders:Concurrency :: unbounded_buffer LeftChopstickProviderBuffer, Concurrency :: unbounded_buffer RightChopstickProviderBuffer;Sekarang aku siap untuk mulai menerapkan metode Filsuf yang akan berjalan di thread sendiri, menunggu ChopstickProviders harus diinisialisasi, dan kemudian mulai bergantian antara berpikir dan makan.Saya menerapkan metode menjalankan virtual dari kelas dasar agen.agent :: run akan dimulai pada tugas sendiri ketika panggilan ke agen :: mulai dibuat.void run () {Hal pertama yang harus saya lakukan dalam menjalankan adalah menginisialisasi ChopstickProviders dengan menunggu pesan yang akan dikirim pada metode umum dengan menerima:/ / Menginisialisasi ChopstickProviders m_LeftChopstickProvider = Concurrency :: terima (LeftChopstickProviderBuffer); m_RightChopstickProvider = Concurrency :: terima (RightChopstickProviderBuffer);Sekarang saya perlu transisi antara berpikir dan makan.Untuk melakukan hal ini saya akan menggunakan dua metode tambahan, PickupChopsticks dan PutDownChopsticks:for (int i = 0; i dilakukan (Concurrency :: agent_done);}Pindah, metode tambahan Makan dan Pikirkan yang mudah.Dalam masalah asli mereka digambarkan sebagai loop berputar acak:swasta: void Makan () {RandomSpin ();}; kekosongan Pikirkan () {RandomSpin ();};};Pelaksana PickupChopsticks secara signifikan lebih menarik karena berhasil mendapatkan dan melepaskan sumpit tanpa memperkenalkan kebuntuan atau kondisi ras.Untuk melaksanakan ini saya akan menggunakan blok pesan lain dari Agen Perpustakaan Asynchronous disebut bergabung.Concurrency :: bergabung adalah blok pesan yang menunggu pesan dari berbagai sumber, berpotensi dari berbagai jenis.Setelah semua pesan telah diterima, menghasilkan pesan konglomerat.Sebuah join dapat mendukung sumber dari jenis yang sama atau ganda dan akan memperoleh pesan secara serakah atau non-serakah.Ini berarti bahwa ada empat varian bergabung dalam agen perpustakaan.Kelas Philosopher akan menggunakan satu tipe bergabung non-serakah.Gambar 3menunjukkan contoh sederhana dari bergabung dalam kode.Gambar 3 Sebuah Gabung Sederhana/ / Membuat dua sumpit Chopstick chopstick1 ("sumpit satu"); Chopstick chopstick2 ("sumpit dua"); / / membuat ChopstickProviders untuk menyimpan sumpit ChopstickProvider chopstickBuffer1, ChopstickProvider chopstickBuffer2, / / menempatkan sumpit di setiap sumpit pemegang Concurrency :: kirim (chopstickBuffer1, & chopstick1); Concurrency :: kirim (chopstickBuffer2, & chopstick2); / / mendeklarasikan satu-jenis non serakah bergabung untuk mendapatkan mereka. / / Parameter konstruktor adalah jumlah input Concurrency :: bergabung j (2); / / menghubungkan penyedia sumpit untuk bergabung sehingga pesan / / dikirim akan merambat ke depan chopstickBuffer1.link_target (& j); chopstickBuffer2.link_target (& j); / / tipe tunggal bergabung pesan blok menghasilkan vektor Sumpit std :: vector hasil = Concurrency :: terima (j);Sekarang aku siap untuk melaksanakan PickupChopsticks.Hal pertama yang harus diperhatikan adalah bahwa Anda kembali satu set sumpit dengan kembali vektor.Untuk mendapatkan sepasang sumpit dari penyedia sumpit berarti menggunakan join non-serakah.Non-serakah varian bergabung menunggu tawaran pesan dari semua sumber terkait, dan kemudian, setelah memiliki tawaran dari masing-masing sumber, menegaskan bahwa hal itu benar-benar dapat mengambil kepemilikan pesan.Inilah yang mencegah kebuntuan dalam contoh ini.Jika saya telah menggunakan serakah sebagai parameter template untuk bergabung, pesan akan diambil secepat menawarkan dibuat, dan cepat atau lambat setiap Philosopher akan memiliki sumpit tunggal dan mereka semua akan menemui jalan buntu.Berikut kode untuk PickupChopsticks.Saya membuat join, link ke penyedia sumpit, dan menunggu sumpit tiba:std :: vector PickupChopsticks () {/ / membuat Concurrency join :: bergabung j (2); m_LeftChopstickProvider-> Nama_Pranala (& j); m_RightChopstickProvider-> Nama_Pranala (& j) ; / / pickup sumpit kembali Concurrency :: terima (j);}Pelaksana PutDownChopsticks sangat mudah juga.Semua harus saya lakukan adalah mengembalikan sumpit yang saya diperoleh dari vektor menggunakan metode asend asynchronous:PutDownChopsticks void (std :: vector & v) {Concurrency :: asend (m_LeftChopstickProvider, v [0]); Concurrency :: asend (m_RightChopstickProvider, v [1]);};

Pengujian Philosopher Dan Menampilkan NegaraKelas Philosopher dapat digunakan sebagai, tetapi Anda perlu memahami bagaimana untuk memulai kelas Filsuf dan memiliki cara melaporkan statusnya-apakah itu makan atau berpikir.Untuk memulai filsuf, hubungi agen :: metode start, yang memunculkan sebuah tugas yang memanggil method run virtual.Untuk melaporkan status, saya memperkenalkan dua blok lagi pesan dari agen perpustakaan: Concurrency :: overwrite_buffer dan Concurrency :: panggilan.Concurrency :: overwite_buffer adalah blok pesan yang menyimpan nilai tunggal yang dapat ditimpa, dan menghasilkan salinan nilai ketika diminta.Seperti dengan blok-blok pesan lainnya, overwrite_buffer bisa dihubungkan dengan target tambahan, dan propagasi pesan yang terjadi dalam rangka.Saya akan menambahkan variabel anggota public untuk kelas Philosopher yang merupakan overwrite_buffer dan memperbaruinya dengan mengirimkan pesan itu sebagai transisi dari Filsuf Berpikir untuk Makan.Secara khusus, ini akan melibatkan menambahkan variabel anggota untuk kelas Philosopher:Concurrency :: overwrite_buffer CurrentState;Ini juga berarti memodifikasi Makan dan Pikirkan untuk memperbarui statusnya:membatalkan Makan () {send (& CurrentState, PhilosopherState :: Makan); RandomSpin ();}; kekosongan Pikirkan () {send (& CurrentState, PhilosopherState :: Berpikir); RandomSpin ();};Concurrency :: panggilan adalah blok pesan yang dibangun dengan functor dan memunculkan sebuah tugas untuk mengeksekusi functor ketika menerima pesan.Anda dapat menggunakan panggilan dalam kombinasi dengan overwrite_buffer baru didefinisikan pada Filsuf untuk melaporkan keadaan, seperti yang ditunjukkan padaGambar 4.Gambar 4 Pelaporan Negara Filsuf/ / Membuat sebuah instance dari Filsuf dan memilikinya mengambil 5 gigitan Filsuf Descartes ("Descartres", 5); / / menciptakan sepasang sumpit Chopstick chopstick1 ("chopstick1"); Chopstick chopstick2 ("chopstick2"); / / buat sepasang ChopstickProviders ChopstickProvider chopstickBuffer1, ChopstickProvider chopstickBuffer2, / / mengasosiasikan penyedia sumpit kami dengan Descartes Concurrency :: kirim (& Descartes.LeftChopstickProvider, chopstickBuffer1); Concurrency :: kirim (& Descartes.RightChopstickProvider, chopstickBuffer2); / / memulai Filsuf asynchronous agent: : memulai (& Descartes); / / deklarasikan sebuah panggilan yang akan digunakan untuk menampilkan filsuf negara / / perhatikan ini menggunakan C + +0 x lambda Concurrency :: panggilan display ([] (PhilosopherState negara) {if ( Nama_Pranala / / link panggilan untuk buffer status di Descartes.CurrentState Filsuf kami, negara == Makan) std :: cout