Java'da çok iş parçacıklı ortamda statik yöntem davranışı


114

Beni rahatsız eden ve kafamda birkaç argüman oluşturan basit, aptalca bir soru var. Aşağıdaki sorularla ilgili tüm şüpheleri atmak istiyorum.

class Clstest{

    public static String testStaticMethod(String inFileStr) {

        // section 0

        // section 1

        // do something with inFileStr

        // section 2

        // section 3

        return inFileStr;

    }

}

Her biri Clstest.testStaticMethod("arg-n")aynı anda bir çağrı yürüten beş iş parçacığı olduğunu varsayalım .

Konu 1 çağrı Clstest.testStaticMethod("arg-1").

İplik 1, bölüm 1'de olduğunda, iş parçacığı 2 çağrıları Clstest.testStaticMethod("arg-2").

O halde 1. Konuya ne olacak? Uyku durumuna geçecek mi?

Konu 1 şansı yakaladığında, yürütmeyi duraklatıldığı 1. bölümden devam ettirecek mi?

Beş iş parçacığı arasında bir Clstest.testStaticMethodve aynı Clstest.testStaticMethodşey paylaşıldığında nasıl olur ?

inFileStrBirden çok iş parçacığı tarafından gönderilenleri değiştirme imkanı var mı ?


Hangi dili hedefliyorsunuz?
ΩmegaMan

3
@ OmegaMan: java
namalfernandolk

Yanıtlar:


192

Hans Passant'ın cevabı güzel. Ama bununla karşılaşan ve Java'ya yeni başlayanlar için biraz daha basit bir şekilde açıklamaya çalışacağımı düşündüm. İşte başlıyor ..

Java'daki bellek iki türe ayrılır - yığın ve yığınlar. Yığın, tüm nesnelerin yaşadığı yerdir ve yığınların işlerini yaptıkları yerlerdir. Her iş parçacığının kendi yığını vardır ve birbirinin yığınlarına erişemez. Her iş parçacığı ayrıca, o anda çalıştırmakta oldukları kod bitini gösteren koda bir işaretçi içerir.

Bir iş parçacığı yeni bir yöntemi çalıştırmaya başladığında, o yöntemdeki argümanları ve yerel değişkenleri kendi yığınına kaydeder. Bu değerlerden bazıları, öbek üzerindeki nesnelere işaret edebilir. Eğer iki iş parçacığı aynı yöntemi aynı anda çalıştırıyorsa, her ikisinin de kod işaretçileri bu yöntemi işaret edecek ve yığınlarında kendi argüman kopyalarına ve yerel değişkenlere sahip olacaktır. Yalnızca yığınlarındaki nesneler yığın üzerindeki aynı nesnelere işaret ederse birbirlerine müdahale ederler. Bu durumda her türlü şey olabilir. Ancak Hans'ın da işaret ettiği gibi, Dizeler değişmezdir (değiştirilemez), bu nedenle "paylaşılan" tek nesne buysa güvendeyiz.

Pek çok iş parçacığı aynı yöntemi çalıştırıyor olabilir. Aynı anda çalışmıyor olabilirler - JVM, Java iş parçacıklarını donanım iş parçacıklarına planlanan işletim sistemi iş parçacıklarına eşlediğinden, makinenizde kaç tane çekirdek bulunduğuna bağlıdır. Bu nedenle, karmaşık senkronizasyon mekanizmaları kullanmadan bu iş parçacığının serpiştirilme şekli üzerinde çok az kontrole sahipsiniz .

Uykunun kendi başına yaptığı bir şey olduğuna dikkat edin.


3
Yani, çok çekirdekli işlemci ortamında aynı kodu aynı anda çalıştıran birden fazla iş parçacığı olabilir, değil mi? Ve tek işlemci ortamında, belirli bir anda çalışan yalnızca bir iş parçacığı vardır. (aralarında zamanı paylaşan birden fazla iş parçacığı.) Öyleyse, iş parçacığı çizelgesi, mevcut dışlama iş parçacığından (A) iş parçacığına (B) şansı verdiğinde, iş parçacığı (A) duraklatıldığı yerden nasıl devam eder? Demek istediğim, özgeçmiş noktasını nasıl biliyor? Bunun nedeni "Her iş parçacığının koda, o anda çalıştırdıkları kod parçasına işaret eden bir işaretçisi de var mı?" Dediğin gibi?
namalfernandolk

6
Sen ona sahipsin. Sadece bazı noktaları açıklığa kavuşturmak için - ilk olarak, iş parçacıklarının nasıl planlandığı Java'nın kontrolü dışındadır. Burada Sun'ın Hotspot JVM'sinden bahsediyorum. JVM, bir Java iş parçacığını bir işletim sistemi iş parçacığına eşler ve işletim sistemi hangi iş parçacığını çalıştıracağına karar verir. Dediğiniz gibi, tek çekirdekli bir makinede işletim sistemi bir seferde yalnızca birini çalıştırabilir, ancak çok çekirdekli bir makinede aynı anda birden fazla çalışabilir. İkinci olarak, bir iş parçacığı ne zaman duraklatıldığının gerçekten farkında değildir, sahip olduğu tek bilgi, program işaretçisi (koda işaret eden) ve tam olarak oldukları gibi kaydedilip geri yüklenen yığın olmasıdır.
selig

Öyleyse, iş parçacıkları yerel kapsamlarının dışında değişkenler kullandığında ve örneğin, bir iş parçacığı değişkenin değerini, diğer iş parçacığı bu değişkeni (veya değişkene göstericiyi) kendi yığınında çekmeden önce güncellediğinde olur. Bu doğru bir anlayış mı?
hariszhr

2
Biraz daha kesin olmak gerekirse ... parazit yalnızca olabilir ve olabilir, ancak iş parçacıkları yığın üzerinde bir şeyler paylaştığında (yerel olmayan) gerçekleşmesi zorunlu değildir. Kodun farklı bölümleri arasındaki bağımlılıklara bağlı olarak girişimin gerçekleşmesinin birkaç farklı yolu vardır. Eksik bazı detaylar olduğu için örneğinizden emin değilim. Belki de A ve B evrelerinin her ikisinin de paylaşılan bir değeri okuduğu ve ardından her ikisinin de okunan değere göre onu güncellediği olası bir sorundan bahsediyorsunuzdur. Bu bir veri yarışı.
selig

1
@selig eğer ex için sadece örnek yöntemlerine sahip bir sınıfım varsa: bir hizmet sınıfı ve bu tekil ise, hizmet sınıfı herhangi bir durumu tutmadığından bir seferde örnek yöntemlerini yürüten birden fazla iş parçacığı hakkında endişelenmeme gerek yok. yalnızca sınıfın örnek değişkenleri varsa mevcuttur. Anladığım doğru mu?
Yug Singh

67

Uyku durumuna geçecek mi?

Hayır, kasıtlı olarak birbirleriyle senkronize olmadıkları sürece bir iş parçacığı çalıştırmak diğer iş parçacıklarını etkilemez. Birden fazla işlemci çekirdeğiniz varsa, tüm son makinelerde vardır, bu iş parçacıkları muhtemelen aynı anda çalışacaktır. Makinenizde yeterli çekirdek olmadığından, 5 iş parçacığı başlattığınızda bu biraz daha az olasıdır. İşletim sistemi aralarında seçim yapmaya zorlanır ve her birine çalışması için biraz zaman tanır. İş parçacığı zamanlayıcının işi. Bu durumda bir iş parçacığı "uyku" durumunda olmayacaktır, sadece duraklatılır ve iş parçacığı zamanlayıcısının ona çalışma şansı vermesini bekler. Programlayıcı tarafından kesintiye uğradığı yerden devam edecektir.

Birden çok iş parçacığı tarafından gönderilen inFileStr'yi değiştirme imkanı var mı?

Böyle bir olasılık yoktur, evrelerin kendi yığınları vardır, bu nedenle herhangi bir yöntem argümanı ve yerel değişken her evre için benzersiz olacaktır. Bir dizginin kullanılması ayrıca dizgelerin değişmez olması nedeniyle bu evrelerin birbirine karışmayacağını garanti eder.

Eğer argüman başka türden değiştirilebilir bir nesneye referans ise böyle bir garanti yoktur. Veya yöntemin kendisi statik olan değişkenler veya öbek üzerindeki nesnelere başvurular kullanıyorsa. Bir iş parçacığı nesneyi değiştirdiğinde ve başka bir iş parçacığı onu okuduğunda eşitleme gereklidir. Kilit C # dilinde kelime böyle gerekli senkronizasyon uygulamak için demirbaş yoludur. Yöntemin statik olması, bu tür bir senkronizasyonun asla gerekli olmadığı anlamına gelmez. Sadece az olasılıkla aynı nesne (paylaşma erişen parçacığı konusunda endişelenmenize gerek yok çünkü bu ).


3
Hata, [java] etiketini hiç görmedim. Yeterince yakın.
Hans Passant

Gönderildiğinde eklemeyi unuttum. Benim hatam. :). Cevap için herhangi bir şekilde teşekkür ederim. Çok yardımcı oldu.
namalfernandolk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.