Java iş parçacıkları işletim sistemi iş parçacıklarına nasıl eşlenir

Bir iş parçacığı, bir program sayacı, yığın, bir dizi kayıt ve iş parçacığı kimliğini içeren temel CPU kullanım birimidir.

Geleneksel (ağır) süreçlerin tek bir kontrol dizisi vardır - bir program sayacı ve herhangi bir zamanda yürütülebilen bir dizi talimat.

Şekil 4.1'de gösterildiği gibi, çok iş parçacıklı bir uygulama tek bir işlemde birden çok iş parçacığına sahiptir.Her iş parçacığının kendi program sayacı, yığını ve kayıt kümesi vardır, ancak ortak kodu, verileri ve belirli yapıları (dosyaları açma gibi) paylaşır.

Şekil 4.1-Tek iş parçacıklı ve çok iş parçacıklı süreçler

Çoklu okumanın dört ana avantajı vardır:

Duyarlılık - Bir iş parçacığı hızlı yanıt sağlayabilirken, diğer iş parçacıkları yoğun hesaplamalar için engellenir veya yavaşlatılır.

Kaynak paylaşımı - Varsayılan olarak, iş parçacıkları ortak kodu, verileri ve diğer kaynakları paylaşır, bu da birden çok görevin aynı anda tek bir adres alanında gerçekleştirilmesine olanak tanır.

Ekonomik - İş parçacıkları oluşturmak ve yönetmek (ve bunlar arasında bağlam geçişi yapmak), bir süreç için aynı görevleri gerçekleştirmekten çok daha hızlıdır.

Ölçeklenebilirlik, yani çok işlemcili mimari-tek iş parçacıklı işlemlerin kullanımı, kaç tane kullanılabilir olursa olsun, yalnızca bir CPU üzerinde çalışabilirken, çok iş parçacıklı uygulamaların yürütülmesi mevcut işlemciler arasında dağıtılabilir. (CPU için rekabet eden birden fazla işlem olduğunda, yani yük ortalaması belirli bir eşiğin üzerinde olduğunda, tek iş parçacıklı işlemlerin yine de çok işlemcili bir mimariden yararlanabileceğini unutmayın.)

Nükleer programlama

Bilgisayar mimarisindeki son trend, birden fazla çekirdek Veya CPU yongası.

Geleneksel tek çekirdekli yongalarda çalışan çok iş parçacıklı uygulamalar Şekil 4.3'te gösterildiği gibi iş parçacıkları arasına eklemelidir.

Bununla birlikte, çok çekirdekli bir yongada, iş parçacıkları, Şekil 4.4'te gösterildiği gibi gerçek paralel işleme elde etmek için mevcut çekirdeklere dağıtılabilir.

İşletim sistemleri için, çok çekirdekli yongalar, mevcut birden çok çekirdekten daha iyi yararlanmak için yeni programlama algoritmaları gerektirir.

Çoklu iş parçacığı daha yaygın ve önemli hale geldikçe (onlarca iş parçacığı yerine binlerce iş parçacığı), donanımda çekirdek başına daha fazla eşzamanlı iş parçacığı desteklemek için CPU'lar geliştirilmiştir.

Çok çekirdekli yongaların zorluğu

Görevleri tanımlayın - aynı anda gerçekleştirilebilecek etkinlikleri bulmak için uygulamayı kontrol edin.

Denge-Bul aynı anda çalışan ve aynı değeri sağlayan görevleri bulun. Yani, önemsiz görevleri tamamlamak için bazı konuları boşa harcamayın.

Veri bölme - İş parçacıkları birbiriyle karışmasını önleyin.

Veri bağımlılığı - Bir görev başka bir görevin sonucuna bağlıysa, doğru sırada erişim sağlamak için görevlerin senkronize edilmesi gerekir.

Test etme ve hata ayıklama - Paralel işleme durumunda, doğası gereği daha zordur, çünkü yarış koşulları daha karmaşık ve tanımlanması zor hale gelir.

Paralel tip

Teorik olarak, iş yüklerini paralelleştirmenin iki farklı yolu vardır:

Veri paralelliği

Verileri birden çok çekirdek (iş parçacığı) arasında bölün ve her veri alt kümesinde aynı görevleri gerçekleştirin. Örneğin, büyük bir görüntüyü birden çok bölüme ayırın ve aynı dijital görüntü işlemeyi farklı çekirdeklerdeki her bölüm üzerinde gerçekleştirin.

Görev paralelliği

Farklı çekirdekler arasında gerçekleştirilecek farklı görevleri bölün ve aynı anda gerçekleştirin.

Uygulamada, herhangi bir program yalnızca bunlardan birine veya diğerine değil, bir tür karışık kombinasyonla bölünecektir.

Çok iş parçacıklı model

Modern sistemlerde yönetilmesi gereken iki tür iş parçacığı vardır: kullanıcı iş parçacıkları ve çekirdek iş parçacıkları.

Kullanıcı iş parçacıkları çekirdek tarafından desteklenir ve çekirdek yönetimi gerektirmez. Bunlar, uygulama programcılarının programlarına ekleyeceği dizilerdir.

Çekirdek iş parçacıkları, işletim sisteminin kendisi tarafından desteklenir ve yönetilir. Tüm modern işletim sistemleri çekirdek düzeyinde iş parçacıklarını destekler ve çekirdeğin aynı anda birden çok görevi gerçekleştirmesine veya birden çok çekirdek sistemi çağrısına hizmet vermesine olanak tanır.

Belirli bir uygulamada, kullanıcı iş parçacıklarını çekirdek iş parçacıklarına eşlemek için aşağıdaki stratejilerden biri kullanılmalıdır.

Çoktan bire model

Çoktan bire modelde, birçok kullanıcı düzeyindeki iş parçacığı tek bir çekirdek iş parçacığı ile eşleştirilir.

İş parçacığı yönetimi, kullanıcı alanındaki iş parçacığı kitaplığı tarafından çok etkilidir.

Ancak, bloke edici bir sistem çağrısı yapılırsa, diğer kullanıcı iş parçacıkları devam edebilse bile tüm süreç engellenecektir.

Tek bir çekirdek iş parçacığı yalnızca tek bir CPU üzerinde çalışabildiğinden, çoktan bire model tek bir işlemin birden çok CPU arasında bölünmesine izin vermez.

Solaris ve GNU taşınabilir iş parçacıklarının yeşil konuları geçmişte çoktan bire bir model uyguladı, ancak şu anda çok az sistem bunu yapmaya devam ediyor.

Bire bir model

Bire bir model, her bir kullanıcı iş parçacığını işlemek için ayrı bir çekirdek iş parçacığı oluşturur.

Bire bir model, sistem çağrılarını engellemeyi ve süreçleri birden çok CPU arasında ayırmayı içeren yukarıda listelenen sorunların üstesinden gelir.

Ancak, bire bir modelin yönetimi daha pahalıdır, daha fazla ek yük gerektirir ve sistemi yavaşlatır.

Bu modelin çoğu uygulaması, yaratılabilecek iş parçacığı sayısını sınırlar.

Hem Windows (Win95'ten başlayarak) hem de Linux bire bir iş parçacığı modelini uyguladı.

Çoktan çoğa model

Çoktan çoğa model, bire bir ve çoka bir modellerin en iyi özelliklerini birleştirerek, aynı veya daha az çekirdek iş parçacığı üzerinde herhangi bir sayıda kullanıcı iş parçacığını yeniden kullanır.

Kullanıcının oluşturulmuş iş parçacığı sayısında bir sınırı yoktur.

Çekirdek sistem çağrılarının engellenmesi tüm süreci engellemeyecektir.

İşlemler birden çok işlemciye dağıtılabilir.

CPU sayısına ve diğer faktörlere bağlı olarak her işleme değişken sayıda çekirdek iş parçacığı atanabilir.

Çoktan çoğa modelinin popüler bir çeşidi, çoktan çoğa veya bire bir işlemlere izin veren iki katmanlı modeldir.

IRIX, HP-UX ve Tru64 UNIX, Solaris 9'dan önce Solaris'in yaptığı gibi iki katmanlı bir model kullanır.

Konu kitaplığı

İş parçacığı kitaplığı, programcılara iş parçacığı oluşturmak ve yönetmek için API'ler sağlar.

İş parçacığı kitaplığı, kullanıcı alanında veya çekirdek alanında uygulanabilir. İlki, çekirdek desteği olmadan yalnızca kullanıcı alanında uygulanan API işlevlerini içerir. İkincisi, sistem çağrılarını içerir ve iş parçacığı kitaplığı desteğine sahip bir çekirdek gerektirir.

Üç ana iş parçacığı kitaplığı:

POSIX Pthreads - POSIX standardının bir uzantısı olarak bir kullanıcı veya çekirdek kitaplığı olarak sağlanabilir.

Win32 iş parçacıkları - Windows sistemlerinde çekirdek düzeyinde kitaplık olarak sağlanır.

Java iş parçacıkları - Java genellikle Java sanal makinesinde çalıştığından, iş parçacığının uygulanması, sisteme bağlı olarak JVM'nin çalıştırdığı herhangi bir işletim sistemi ve donanıma, yani Pthreads veya Win32 iş parçacıklarına dayanır.

Java dizisi

Tüm Java programları Threads - hatta "ortak" tek iş parçacıklı programları kullanır.

Yeni evrelerin oluşturulması, Çalıştırılabilir arabirimi uygulayan nesneler gerektirir, bu da onların bir "public void run ()" yöntemini içerdikleri anlamına gelir. Thread sınıfının soyundan gelenler, doğal olarak bu tür yöntemleri içerecektir. (Aslında, iş parçacığının herhangi bir gerçek işlevi olması için run () yöntemi yeniden yazılmalı / sağlanmalıdır.)

Bir iş parçacığı nesnesinin yaratılması iş parçacığını çalıştırmaya başlamaz - bunun için program Thread'in "start ()" yöntemini çağırmalıdır. Start (), Thread için bellek ayırır ve başlatır ve ardından run () yöntemini çağırır. (Programcı doğrudan run () öğesini çağırmaz.)

Java genel değişkenleri desteklemediğinden, verileri paylaşmak için Paylaşılan Nesne başvurusuna İş Parçacıkları iletmelisiniz.

Lütfen JVM'nin yerel işletim sisteminin üstünde çalıştığını ve JVM belirtiminin Java iş parçacıklarını çekirdek iş parçacıklarıyla eşlemek için bir model belirtmediğini unutmayın. Bu karar, bire bir, çoktan çoğa veya çoktan bire olabilen JVM uygulamasına bağlıdır. (UNIX sistemlerinde, JVM genellikle PThreads kullanır ve Windows sistemlerinde genellikle Windows iş parçacıkları kullanır.)

"Java'da Global Değişkenler" Statik anahtar sözcüğü ile tanımlanan genel sınıf genel alanları olan Java'da global değişkenler kavramı yoktur.

Konu Havuzu

Her seferinde yeni bir iş parçacığı oluşturmanız ve işiniz bittiğinde onu silmeniz gerektiğinde, bu verimsiz olabilir ve ayrıca çok büyük (sınırsız) sayıda iş parçacığının oluşturulmasına neden olabilir.

Diğer bir çözüm, işlem ilk başladığında birden çok iş parçacığı oluşturmak ve bu iş parçacıklarını iş parçacığı havuzuna koymaktır. İşlemleri gerektiği gibi havuzdan ayırın ve artık gerekmediğinde havuza geri dönün. Havuzda kullanılabilir iş parçacığı yoksa, işlemin bir tane kullanılabilir olana kadar beklemesi gerekebilir.

İş parçacığı havuzunda bulunan (maksimum) iş parçacığı sayısı, ayarlanabilir parametrelerle belirlenebilir ve değişen sistem yüklerine dinamik olarak yanıt verebilir.

Win32, "PoolFunction" işlevi aracılığıyla bir iş parçacığı havuzu sağlar. Java ayrıca, java.util.concurrent paketi aracılığıyla iş parçacığı havuzları için destek sağlar ve Apple, Grand Central Dispatch mimarisi altındaki iş parçacığı havuzlarını destekler.

Sinyal işleme

Soru: Çok iş parçacıklı bir süreç bir sinyal aldığında, sinyal hangi iş parçacığına iletilmelidir?

Cevap: Dört ana seçenek vardır:

Sinyali, sinyalin uygulandığı iş parçacığına iletin.

Sinyali süreçteki her iş parçacığına iletin.

Sinyali süreçteki belirli konulara iletin.

İşlemdeki tüm sinyalleri almak için belirli bir iş parçacığı atayın.

En iyi seçim, hangi özel sinyalin dahil olduğuna bağlı olabilir.

UNIX, bireysel iş parçacıklarının hangi sinyalleri kabul ettiklerini ve hangi sinyalleri göz ardı ettiklerini belirtmelerine izin verir. Bununla birlikte, sinyal yalnızca belirli bir sinyali alan ilk iş parçacığı olan bir iş parçacığına geçirilebilir.

UNIX, iki bağımsız sistem çağrısı sağlar: sırasıyla işlemlere veya belirli evrelere sinyal göndermek için kullanılan kill (pid, signal) ve pthread_kill (tid, signal).

Windows sinyalleri desteklemez, ancak asenkron prosedür çağrıları (APC) kullanarak bunları simüle edebilirsiniz. APC, bir işleme değil, belirli bir iş parçacığına aktarılır.

İş parçacığı iptali

Artık ihtiyaç duyulmayan bir iş parçacığı, iki yoldan biriyle başka bir iş parçacığı tarafından iptal edilebilir:

Eşzamansız iptal, iş parçacığını hemen iptal eder.

Gecikmeli iptal, iş parçacığının uygun olduğunda kendisini iptal etmesi gerektiğini belirten bir bayrak belirler. Bu bayrak daha sonra iptal edilen iş parçacığı tarafından periyodik olarak kontrol edilir ve bayrak setini gördüğünde güzelce çıkar.

Kaynak tahsisinin zaman uyumsuz iptali (paylaşılan) ve iş parçacıkları arasında veri aktarımı sorunlu olabilir.

Yerel depolama iş parçacığı

Çoğu veri, iş parçacığı arasında paylaşılır, bu da iş parçacığı kullanmanın temel faydalarından biridir.

Ancak bazen iş parçacıkları da iş parçacığına özgü veriler gerektirir.

Çoğu ana iş parçacığı kitaplığı (pThreads, Win32, Java) iş parçacığı yerel depolama veya TLS adı verilen iş parçacığına özgü verileri destekler. Bunun yerel bir değişkenden çok statik verilere benzediğini unutmayın, çünkü işlevin sonunda varlığını sürdürmez.

Linux iş parçacığı

Linux süreçler ve iş parçacıkları arasında ayrım yapmaz - daha genel bir terim olan "Görev" kullanır.

Geleneksel fork () sistem çağrısı, daha önce bahsedildiği gibi bir işlemi (Görev) tamamen kopyalar.

Başka bir sistem çağrısı clone (), aşağıdaki tabloda gösterilen Bayrak tarafından kontrol edilen üst ve alt görevler arasında farklı paylaşım düzeylerine izin verir:

Flag ayarlanmadan clone () çağrısı fork () ile eşdeğerdir. CLONE_FS, CLONE_VM, CLONE_SIGHAND ve CLONE_FILES ile clone () çağırmak bir iş parçacığı oluşturmaya eşdeğerdir, çünkü tüm bu veri yapıları paylaşılacaktır.

Linux bunu başarmak için task_struct yapısını kullanır, bu da esas olarak görev kaynakları için bir dolaylı yönlendirme seviyesi sağlar. Bayrak ayarlanmazsa, yapının gösterdiği kaynak kopyalanır, ancak bayrak ayarlanırsa, yalnızca kaynağa işaretçi kopyalanır, böylece kaynak paylaşılır. (OO programlamada derin kopyalama ve yüzeysel kopyalama hakkında düşünün.)

Birkaç Linux dağıtımı artık NPTL'yi (Yerel POXIS İş Parçacığı Kitaplığı) destekliyor

POSIX standartlarına uyun.

SMP (simetrik çoklu işlem), NUMA (tek tip olmayan bellek erişimi) ve çok çekirdekli işlemcileri destekler.

Yüzlerce ila binlerce iş parçacığını destekleyin.

"Linux Thread Modelinin Karşılaştırması: LinuxThreads ve NPTL"

Linux ilk geliştirildiğinde, çekirdekte iş parçacıkları gerçekten desteklenmiyordu. Ancak süreci, clone () sistem çağrısı aracılığıyla planlanabilir bir varlık olarak ele alabilir. Bu çağrı, çağrı işlemiyle aynı adres alanını paylaşan çağrı işleminin bir kopyasını oluşturur. LinuxThreads projesi, iş parçacığı desteğini tamamen kullanıcı alanında simüle etmek için bu çağrıyı kullanır. Ne yazık ki, bu yaklaşımın bazı dezavantajları, özellikle sinyal işleme, programlama ve süreçler arasındaki senkronizasyon ilkelleri ile ilgili sorunlar vardır. Ayrıca, bu diş açma modeli POSIX gereksinimlerini karşılamıyor.

LinuxThreads'i iyileştirmek için, açıkça çekirdek desteğine ihtiyacımız var ve iş parçacığı kitaplığını yeniden yazmamız gerekiyor. İki rakip proje bu gereksinimleri karşılamaya başladı. IBM geliştiricilerinden oluşan bir ekip, NGPT (Yeni Nesil POSIX Threads) projesini başlattı. Aynı zamanda, Red Hat'taki bazı geliştiriciler NPTL projesini başlattı. NGPT, 2003 yılının ortalarında terk edildi ve bu alanı tamamen NPTL'ye bıraktı.

NPTL veya Native POSIX Thread Library, Linux iş parçacığının yeni bir uygulamasıdır.LinuxThreads'in eksikliklerinin üstesinden gelir ve ayrıca POSIX gereksinimlerini karşılar. LinuxThreads ile karşılaştırıldığında, performans ve kararlılıkta önemli gelişmeler sağlar. LinuxThreads gibi, NPTL de bire bir model uygular.

"Ünlü c10k kağıdı"

Biraz eski olmasına rağmen yine de okumaya değer.

Not: 1: 1 dişli ve M: N dişli

İş parçacığı kitaplığını uygularken bir seçim vardır: tüm iş parçacığı desteğini çekirdeğe koyabilirsiniz (buna 1: 1 iş parçacığı modeli denir) veya önemli bir bölümünü kullanıcı alanına taşıyabilirsiniz (buna M: N iş parçacığı denir) modeli). Bir şey var, M: N'nin daha yüksek performans olduğu düşünülüyor, ancak bunu doğru yapmak için çok karmaşık ve çoğu insan bundan uzak duruyor.

"Java iş parçacıklarını işletim sistemi iş parçacıklarına nasıl eşleyebilirim?

JVM iş parçacıklarının işletim sistemi iş parçacıklarıyla eşlenmesi yaygın bir okuma ifadesidir. Ama bu ne anlama geliyor? Java'da bir Thread nesnesi oluşturuyoruz ve yeni bir thread başlatmak için onun start metodunu çağırıyoruz. OS iş parçacığını nasıl başlatır? Ve Thread nesnesinin run metodu çalıştırılan OS thread'e nasıl eklenir?

Yerel bir yöntem olarak bildirilen start0 yöntemini çağırın. "Yerel" etiket, JVM'ye bunun platforma özgü yerel bir yöntem (C / C ++ ile yazılmış) olduğunu ve java yerel arabirimi aracılığıyla çağrılması gerektiğini söyler. JNI, Java'nın yerel kodun JVM ile nasıl entegre edileceğini ve bunun tersini belirten yerel yöntem arabirim spesifikasyonudur. (Https://docs.oracle.com/javase/9 /docs/specs/jni/design.html#jni-interface-functions-and-pointers)

Java'dan C ++ 'ya, JVM perspektifinden Java iş parçacıklarının oluşturulmasına ve çalışmasına bakın

Referans: [JVM kaynak kodu araştırması] Thread.run () öğesinin temelde yatan uygulamasının derinlemesine anlaşılması

Örnek olarak jdk8'i ele alalım:

Yeni java.lang.Thread.start () aracılığıyla bir iş parçacığı başlatmak için, yalnızca iş mantığını run () yöntemine koymanız, bir Java iş parçacığı başlatmanız ve start () yöntemini çağırmanız gerekir:

\ Openjdk-8u40-src-b25-10_feb_2015 \ openjdk \ jdk \ src \ share \ classes \ java \ lang \ Thread.java içinde

Bir iş parçacığı başlatılırken, yerel yöntem start0 () çağrılacaktır. Yerel yöntemlerin kaydı için, lütfen registerNatives () 'in derinlemesine uygulanmasına [JVM kaynak kodu keşfi] bakın.

Java sistem paketi altında, örneğin:

java.lang.System

java.lang.Object

java.lang.Class

RegisterNatives () adında yerel bir yöntemi yürütmek için kullanılan statik bir blok vardır:

\ openjdk-8u40-src-b25-10_feb_2015 \ openjdk \ jdk \ src \ share \ native \ java \ lang \ Thread.c

start0, JVM_StartThread'e karşılık gelir

VM_StartThread yöntemi \ openjdk-8u40-src-b25-10_feb_2015 \ openjdk \ hotspot \ src \ share \ vm \ prims \ jvm.cpp konumunda bulunur.

// C ++ Thread yapısını tahsis edin ve yerel thread yaratın.

// Java'dan alınan yığın boyutu imzalandı, ancak kurucu gerektirir

// size_t (işaretsiz tür), bu nedenle lütfen negatif değerleri iletmekten kaçının

// Çok büyük bir yığına yol açar.

Native_thread = new JavaThread (thread_entry, sz) kodu; JavaThread'in bir örneğini oluşturmak için kullanılır,

\ openjdk-8u40-src-b25-10_feb_2015 \ openjdk \ hotspot \ src \ share \ vm \ runtime \ thread.cpp

// Buradaki _osthread NULL olabilir çünkü hafızamız yetersiz (çok fazla aktif evre).

// OutOfMemoryError'ı atmamız gerekiyor-ama bunu yapamayız çünkü arayan

// Bir kilidi tutabilir ve bir istisna atmadan önce tüm kilitlerin kilidi açılmalıdır (

// İstisna, bir istisna nesnesi oluşturmayı ve onu başlatmayı,

// VM'den JavaCall aracılığıyla ayrılacak ve ardından tüm kilitlerin kilidi açılmalıdır.

// Buraya geldiğimizde, konu hala askıya alınmış durumda. Konu açıkça başlatılmalıdır

// Yaratıcı tarafından! Ek olarak, ileti dizileri açıkça "ileti dizileri" listesine eklenmelidir

// Threads çağırarak: add. Bunun yapılmamasının nedeni iş parçacığının

// Nesne tamamen başlatılmalıdır (JVM_Start'a bakın)

\ Openjdk-8u40-src-b25-10_feb_2015 \ openjdk \ hotspot \ src \ os \ linux \ vm \ os_linux.cpp konumunda bulunan işletim sistemi aracılığıyla iş parçacığı oluşturun

bool os :: create_thread (Thread * thread, ThreadType thr_type, size_t stack_size) {

iddia (thread- > osthread () == NULL, "sorumlu arayan");

// OSThread nesnesini ayırın

OSThread * osthread = new OSThread (NULL, NULL);

eğer (osthread == NULL) {

yanlış dönüş;

}

// doğru iş parçacığı durumunu ayarlayın

osthread- > set_thread_type (thr_type);

// Başlangıç durumu TAHSİS EDİLDİ, ancak BAŞLATILMADI

osthread- > set_state (TAHSİS EDİLEN);

Konu- > set_osthread (osthread);

// iş parçacığı özniteliklerini init

pthread_attr_t attr;

pthread_attr_init (attr);

pthread_attr_setdetachstate (attr, PTHREAD_CREATE_DETACHED);

// yığın boyutu

if (os :: Linux :: supports_variable_stack_size ()) {

// arayan tarafından belirtilmezse yığın boyutunu hesapla

eğer (stack_size == 0) {

stack_size = os :: Linux :: default_stack_size (thr_type);

switch (thr_type) {

case os :: java_thread:

// Java iş parçacıkları, varsayılan değer olan ThreadStackSize'ı kullanır

// -Xss bayrağıyla değiştirildi

assert (JavaThread :: stack_size_at_create () > 0, "bu ayarlanmalıdır");

stack_size = JavaThread :: stack_size_at_create ();

kırmak;

case os :: compiler_thread:

if (CompilerThreadStackSize > 0) {

stack_size = (size_t) (CompilerThreadStackSize * K);

kırmak;

} // aksi takdirde:

// CompilerThreadStackSize tanımlanmamışsa VMThreadStackSize kullanın

case os :: vm_thread:

case os :: pgc_thread:

case os :: cgc_thread:

case os :: watcher_thread:

eğer (VMThreadStackSize > 0) stack_size = (size_t) (VMThreadStackSize * K);

kırmak;

}

}

stack_size = MAX2 (stack_size, os :: Linux :: min_stack_allowed);

pthread_attr_setstacksize (attr, stack_size);

} Başka {

// pthread_create () varsayılan değeri seçsin.

}

// glibc koruma sayfası

pthread_attr_setguardsize (attr, os :: Linux :: default_guard_size (thr_type));

ThreadState durumu;

{

// Sabit yığın LinuxThreads ile çalışıyorsak iş parçacığı oluşturmayı serileştir

bool kilidi = os :: Linux :: is_LinuxThreads ()! os :: Linux :: is_floating_stack ();

eğer (kilitle) {

os :: Linux :: createThread_lock () - > lock_without_safepoint_check ();

}

pthread_t tid;

int ret = pthread_create (tid, attr, (void * (*) (void *)) java_start, thread);

pthread_attr_destroy (attr);

eğer (ret! = 0) {

eğer (PrintMiscellaneous (Ayrıntılı || WizardMode)) {

perror ("pthread_create ()");

}

// Şimdiye kadar ayırdığımız şeyleri temizlememiz gerekiyor

Konu- > set_osthread (NULL);

osthread'i sil;

if (kilitle) os :: Linux :: createThread_lock () - > Kilidini aç();

yanlış dönüş;

}

// pthread bilgisini OSThread'de saklayın

osthread- > set_pthread_id (tid);

// Alt iş parçacığı başlatılana veya durdurulana kadar bekleyin

{

* Sync_with_child = osthread- izleyin > startThread_lock ();

MutexLockerEx ml (sync_with_child, Mutex :: _ no_safepoint_check_flag);

while ((durum = osthread- > get_state ()) == TAHSİS EDİLDİ) {

sync_with_child- > bekleyin (Mutex :: _ no_safepoint_check_flag);

}

}

eğer (kilitle) {

os :: Linux :: createThread_lock () - > Kilidini aç();

}

}

// İş parçacığı sınırına ulaşıldığı için iptal edildi

if (state == ZOMBIE) {

Konu- > set_osthread (NULL);

osthread'i sil;

yanlış dönüş;

}

// İş parçacığı askıya alındı (INITIALIZED durumunda),

// ve çağrı zincirinde daha yukarılarda başlatılır

assert (durum == BAŞLATILDI, "yarış durumu");

doğruya dön;

}

esasen

// Bir iş parçacığı oluşturmak için sistem kitaplığını çağırın, thread_native_entry yerel Java iş parçacığının yürütme girdisidir //

int ret = pthread_create (tid, attr, (void * (*) (void *)) thread_native_entry, thread);

Bu yöntem, C ++ 'ın bir iş parçacığı oluşturması için bir kitaplık yöntemidir.Bu yöntem çağrıldığında, bir C ++ iş parçacığı oluşturulacak ve iş parçacığı hazır durumuna girecek, yani çalışmaya başlayabilir

Pek çok yerli programcı var, neden kendi programlama dilinizi geliştirmiyorsunuz?
önceki
Veri ambarı nedir? Anlayışım hakkında konuş
Sonraki
Çin'deki birçok eyalet, Wenshan Huihai'yi düzeltmek için işe alıyor En pratik eyalet Shandong
Asya moda yüzlerinin listesi açıklandı Listenin başında Ni Ni nerede?
İlk sekreter milyonlarca "sadaka"! Lingang köyü büyük bir şey yapmak zorunda!
ThreadLocal ilkesini anlamak için bir resim
Harika! Lingang'daki bir başka büyük proje başarıyla devreye alındı! İkinci aşama otomotiv endüstrisine girecek ~
Bu itfaiyecinin özçekimi üzücü
Toplamak! Nanjing Snacks Haritası
Büyük veri kariyer planlaması için doğru duruş
Java dizesi oluşturmak için "" veya yapıcı kullanılsın mı?
Kadın Mercedes-Benz otomobil sahipleri 4S mağazası ile uzlaştı, diğer otomobil sahipleri finansal hizmet ücretlerini iade etmeyi reddetti
BAT Mülakat Soruları Serisi: JVM bellek alanının derinlemesine analizi ve bellek taşması analizi
Şehrin eğitim konferansı düzenlendi ve belediye parti komitesi sekreteri bu endişe verici konulara herkese yanıt verdi
To Top