Statik sınıf değişkenlerini değiştirmezlerse, senkronize edilmemiş statik yöntemler iş parçacığı güvenli midir?


145

Sana olan statik bir yöntemi varsa merak değil senkronize fakat yok değil statik değişkenlerini değiştirmek o evreli mı? Ya yöntem kendi içinde yerel değişkenler yaratırsa? Örneğin, aşağıdaki kod iş parçacığı için güvenli midir?

public static String[] makeStringArray( String a, String b ){
    return new String[]{ a, b };
}

Dolayısıyla, bu yöntemi sürekli ve aynı anda çağıran iki iş parçacığım varsa, biri köpeklerle ("büyük dane" ve "boğa köpeği" deyin), diğeri de kedilerle ("farsça" ve "siyam" deyin) hiç kedi ve köpek alacak mıyım aynı dizide mi? Ya da kediler ve köpekler asla aynı zamanda aynı yöntemin çağrısı içinde olmayacaklar mı?


bu konuyla ilgili başka bir konu: stackoverflow.com/questions/8015797/…
象 嘉 道

2
Bu farklı bir sorudur, bu statik yöntem çağrısının diziler değil, iş parçacığı açısından güvenli olup olmadığıdır.
Kızak

Yanıtlar:


212

Bu yöntem% 100 iş parçacığı güvenlidir, olmasa bile olurdu static. İş parçacığı güvenliği ile ilgili sorun, iş parçacıkları arasında veri paylaşmanız gerektiğinde ortaya çıkar - atomiklik, görünürlük vb. Konulara dikkat etmelisiniz.

Bu yöntem yalnızca yığın üzerinde bulunan parametreler ve öbek üzerindeki değişmez nesnelere referanslar üzerinde çalışır. Yığın, doğası gereği iş parçacığı için yereldir , bu nedenle hiçbir zaman veri paylaşımı olmaz.

Değişmez nesneler ( Stringbu durumda) aynı zamanda iş parçacığı açısından güvenlidir çünkü oluşturulduktan sonra değiştirilemezler ve tüm iş parçacıkları aynı değeri görür. Öte yandan, yöntem kabul ederse (değiştirilebilir) Datebir sorunla karşılaşmış olabilirsiniz. İki iş parçacığı aynı nesne örneğini aynı anda değiştirerek yarış koşullarına ve görünürlük sorunlarına neden olabilir.


4
Doğru cevap. Yöntem düzeyi değişkenleri, her iş parçacığı yürütme yığınında kopyalanır.
Sid

teknik olarak yöntem satır içi olacaktır ve parametreler CPU kayıtları olacaktır. Yine de cevap doğru
bestsss

43
Yığın elbette geçerli iş parçacığı için yereldir, ancak bu yığındaki paylaşılan nesnelere referanslarınız olabilir. Bu örnekte bir sorun değildir çünkü Dizeler değişmezdir, ancak geçirilen bir parametreyi değiştiren bir yöntem, bu iletilen nesneye birden çok iş parçacığından erişilebiliyorsa iş parçacığı güvenlik sorunları yaşayabilir.
Jörn Horstmann

1
@TomaszNurkiewicz'in de bahsettiği gibi değişken bir nesne referansını geçersek yarış koşullarına girebiliriz. Yöntem nesneyi herhangi bir şekilde değiştirmese bile bu doğru mu? Demek istediğim, nesne değişebilir olduğu için yine de bir yarış durumu olarak sınıflandırılacak mı? Ve parametrelere son anahtar kelimeyi eklersek ne olur?
Rafay

Yöntemde sınıf nesnesini iletirsem ne olur? Değişken yığın veya yığın içinde olacak mı?
grep

28

Bir yöntem yalnızca bazı paylaşılan durumları değiştirdiğinde iş parçacığı açısından güvenli olmayabilir. Statik olup olmaması önemli değildir.


3
@Konrad_Garus Buradaki soru, yerel değişkenlerin paylaşılan durumu oluşturup oluşturmadığı veya statik bir yöntem için yığının iş parçacığı başına mı yoksa paylaşımlı mı olduğu yönündeydi.
Kızak

"Bir yöntem, yalnızca paylaşılan bir durumu değiştirdiğinde iş parçacığı açısından güvenli olmayabilir." Hayır, değiştirmeden yalnızca paylaşılan duruma erişirse, iş parçacığı güvenli olmayabilir. Değişken bir nesneye eşitlenmemiş erişim, diğer iş parçacığı uygun şekilde eşitlenmiş olsa bile nesne başka bir iş parçacığı tarafından değiştiriliyorsa tutarsız duruma erişebilir. İş parçacığı güvenliğinin sürdürülmesi için her iki iş parçacığı da uygun senkronizasyona ihtiyaç duyar.
Warren Dew

12

İşlev, iş parçacığı için tamamen güvenlidir.

Düşünürseniz ... bu farklı olsaydı ne olacağını düşünün. Her olağan işlev, senkronize edilmemişse iş parçacığı sorunlarına sahip olacaktır, bu nedenle JDK'daki tüm API işlevlerinin senkronize edilmesi gerekir, çünkü bunlar potansiyel olarak birden çok evre tarafından çağrılabilir. Ve çoğu zaman uygulama bazı API kullandığından, çok iş parçacıklı uygulamalar etkili bir şekilde imkansız olacaktır.

Bu, düşünmek için çok saçma, bu yüzden sadece sizin için: Sorunların olmasının açık bir nedeni varsa, yöntemler iş parçacığı açısından güvenli değildir. Her zaman, benim fonksiyonumda birden fazla iş parçacığı olsaydı, ve bir adım hata ayıklayıcınız olsaydı ve bir adım birbiri ardına birinciyi ilerletirseniz ... sonra ikinci iş parçacığını ... belki ikinci iş parçacığını tekrar düşünmeye çalışın ... sorunlar olur mu? Bir tane bulursanız, iş parçacığı güvenli değildir.

Ayrıca, ConcurrentHashMap gibi belirtilenler dışında Java 1.5 Collection sınıflarının çoğunun iş parçacığı için güvenli olmadığını lütfen unutmayın.

Ve gerçekten buna dalmak istiyorsanız, geçici anahtar kelimeye ve TÜM yan etkilerine yakından bakın. Semaphore () ve Lock () sınıfına ve java.util.Concurrent'daki arkadaşlarına bir göz atın. Sınıflarla ilgili tüm API belgelerini okuyun. Öğrenmeye ve tatmin etmeye de değer.

Bu aşırı ayrıntılı cevap için özür dilerim.


2
"Düşünürseniz ... farklı olsaydı ne olacağını düşünün. Her olağan işlev, senkronize edilmezse iş parçacığı sorunları yaşar, bu nedenle JDK'daki tüm API işlevlerinin senkronize edilmesi gerekir, çünkü bunlar potansiyel olarak birden çok kişi tarafından çağrılabilir. İş Parçacığı." İyi bir nokta!
Kızak

1

İş staticparçacıkları arasında paylaşılan statik verileri değiştirmek için senkronize edilmiş statik yöntemlerle anahtar sözcüğü kullanın . staticAnahtar kelime ile oluşturulan tüm iş parçacıkları, yöntemin tek bir sürümü için mücadele edecektir.

Kullan volatileher iş parçacığı paylaşılan veri ve hiçbir okuma kendi kopyasını sahip olduğunu garanti edecek senkronize örneği yöntemleri ile birlikte anahtar kelimeyi / yazma konuları arasında sızıntı yapar.


0

Dize nesnelerinin değişmez olması, yukarıdaki iş parçacığı güvenli senaryo için başka bir nedendir. Bunun yerine, değişken nesneler kullanılırsa (örneğin makeMutableArray ..) o zaman kesinlikle iş parçacığı güvenliği bozulacaktır.


Soru, statik bir yöntem çağrısının başka bir iş parçacığından aynı yönteme yapılan başka bir çağrının argümanlarını görüp görmeyeceğiydi. Cevap yankılanan bir "hayır!" Bunu biliyordum ama şüpheli iş arkadaşlarına kanıtlayabilmek istiyordum.
Kızak

Bu yanıt neden reddedildi? Diğer cevapların katkıda bulunmadığı nokta, değişkenliğin iç ve dış sınır olabileceğidir. Bir değişken döndürürseniz, iş parçacığı güvenli değilsinizdir. Soru, sorunun sorusunu yorumun ima ettiği kadar dar bir şekilde ortaya koymuyor; Kod örneğinden sonraki genişletilmiş soru kodla ifade edilebilir, belki bir birim testi olarak. Ama iş arkadaşlarımı ikna etmeye çalışmaktan hoşlanıyorum. "Bana, test koduma veya Josh Bloch'a inanmıyorlar, ancak belki SO'da bir yanıtı kabul edecekler."
som-snytt
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.