Java'nın senkronize anahtar kelimenin C # sürümü?


313

C # java "senkronize" anahtar kelimenin kendi sürümüne sahip mi?

Yani java'da bir işleve, bir nesneye veya bir kod bloğuna şu şekilde belirtilebilir:

public synchronized void doImportantStuff() {
   // dangerous code goes here.
}

veya

public void doImportantStuff() {
   // trivial stuff

   synchronized(someLock) {
      // dangerous code goes here.
   }
}

3
Blok formu kilitlemek için bir başvuru gerektirir. Yöntem formunda kilit nesnesi dolaylı olarak budur (veya Statik yöntemler için Sınıf [this.class, getClass ()] değil, ancak Sınıflar üzerinde kilitlenmez).
Tom Hawtin - tackline

1
Hala korunmuyor musunuz? Buraya her zaman gelirim çünkü o [MethodImpl(MethodImplOptions.Synchronized)]çizgiyi hatırlayamıyorum .
Bitterblue

1
Sanırım 2. snippet'iniz derlenmeyecek - bir şeyle senkronize edilmesi gerekiyor .
PoweredByRice

Yanıtlar:


466

İlk olarak - çoğu sınıfın asla iş parçacığı için güvenli olması gerekmez. YAGNI kullanın : iplik güvenliğini yalnızca gerçekten kullanacağınızı bildiğinizde uygulayın (ve test edin).

Yöntem düzeyindeki şeyler için [MethodImpl]:

[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}

Bu aynı zamanda erişimcilerde de kullanılabilir (özellikler ve olaylar):

private int i;
public int SomeProperty
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    get { return i; }
    [MethodImpl(MethodImplOptions.Synchronized)]
    set { i = value; }
}

Alan benzeri olayların varsayılan olarak senkronize edildiğini, ancak otomatik olarak uygulanan özelliklerin olmadığını unutmayın :

public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized

Şahsen, MethodImplkilitlendiği gibi uygulanmasını sevmiyorum thisya da typeof(Foo)- en iyi uygulamaya karşı. Tercih edilen seçenek kendi kilitlerinizi kullanmaktır:

private readonly object syncLock = new object();
public void SomeMethod() {
    lock(syncLock) { /* code */ }
}

Alan benzeri olaylar için kilitleme uygulamasının derleyiciye bağlı olduğunu unutmayın; eski Microsoft derleyicilerinde bir lock(this)/ lock(Type)- ancak, daha yeni derleyicilerdeInterlocked güncellemeler kullanır - bu yüzden kötü parçalar olmadan iş parçacığı için güvenlidir.

Bu, daha ayrıntılı kullanım sağlar ve iş parçacıkları arasında iletişim kurmak için Monitor.Wait/ Monitor.Pulseetc kullanımına izin verir .

Alakalı bir blog girişi (daha sonra tekrar ziyaret edilir ).


@earcam ve sorunuz? Bu ifade doğrudur. Sınıfların büyük çoğunluğunun iş parçacığı için güvenli olma zorunluluğu yoktur, iş parçacığı güvenliği için test edilmez ve iş parçacığı güvenliğine sahip olmak performansı etkiler. Dişler hakkında gerçekten endişelenmeniz gereken türlerin sayısı çok azdır - kasıtlı olarak senkronize edilmiş koleksiyonlar, çoklayıcılar, vb.
Marc Gravell

4
Sanırım basitçe söylemeliydim; "çoğu sınıfın hiçbir zaman iş parçacığı için güvenli olması gerekmez", ancak "tüm geliştiriciler eşzamanlılık konusunda farkında olmalıdır" Geriye baktığımda, sayının çok küçük olduğunu kabul ediyorum (ve kesinlikle bir yerde bir kez doğru almak istediğiniz bir şey, sınıfların çoğunun çok iş parçacıklı ortamlarına kayıtsız etkileşime girmesine izin veriyor). Keşke yorumu daha hızlı
silseydim

6
Marc'ın bağlantılı blog yayını , Mart 4.0'da .NET 4.0'da MethodImplve alan benzeri olayların artık iyi senkronizasyon kodu oluşturduğunu ve artık kendi kilitlerinizi kullanmanız gerekmediğini söyleyen bir takibe sahiptir .
Rory O'Kane

2
Günümüzde uygulamaların büyük bir çoğunluğu web tabanlı olup, ağır örneklerin yeniden kullanımı ve bağımlılık enjeksiyonu yoluyla karmaşık nesne yaşam döngüsüne dayanan çerçevelerle sunulmaktadır. Bugünlerde varsayılan zihniyet iş parçacığı güvenliğinin yanına yönelme eğilimindedir.
Sheepy

1
@Elazar artık çok geç, ancak kayıt için: .net standart / .net çekirdek şablonlarını kullanarak oluşturduysanız, çerçeveyi değiştirmek, csproj'da tek satırlık bir değişikliktir ve çoklu olarak normal .net kullanılabilir -targeting. Bununla birlikte, IDE takımları sadece korkunç - sadece neyi değiştirebileceğini ve neyi değiştirebileceğini bilmelisin :)
Marc Gravell

56
static object Lock = new object();

lock (Lock) 
{
// do stuff
}

10
Kilit nesnenizi statik olarak bildirmek istediğinizden emin misiniz?
serg10

21
Elbette, böylece her bir Konu referans göndermeden kolayca erişebilir.
Jan Gressmann

33
Sorucunun sorusu bağlamında olursak, örnek yöntemler hakkında konuşuyoruz. Statik kullanmak, iş parçacığı 1 example1.DoSomething () öğesini çağırır ve iş parçacığı 2, example2.DoSomething öğesini çağırırsa, ikinci çağrı tamamen farklı bir nesne olsa bile engellenir. Birisi aynı nesne üzerinde DoSomething çağrısı yapmadığı sürece thread2'nin çağrısı engellenmemelidir . Yanıldığınızı söylememek, ancak burada statik kullanmanın etkisini anlamak önemlidir, çünkü örnek başına değil küresel olarak engelleyerek performansın düşmesine neden olabilir.
AaronLS

1
@AaronLS Nesneniz kendisinden daha büyük bir kapsamda eylem gerçekleştirdiğinde çok kullanışlıysa statik kilit. Her zaman örneğin web servisleri ile olur.
Thibault D.Nis

4
-1, OP'nin istediği şeyden farklı bir davranış olduğu için. Bu bir sınıf kilidi, örnek kilidi değil.
tster

39

C # java "senkronize" anahtar kelimenin kendi sürümüne sahip mi?

Hayır. C # 'da, lockeşzamansız olarak eşzamansız iş parçacıkları üzerinde çalışmak istediğiniz kaynakları açıkça . lockbir blok açar; yöntem düzeyinde çalışmaz.

Bununla birlikte, temel mekanizma benzerdir, çünkü çalışma zamanında lockçağrılarak Monitor.Enter(ve daha sonra Monitor.Exit) çalışır . Sun belgelerine göre Java da aynı şekilde çalışır .


3
Eşdeğer bir "anahtar kelime" yoktur, ancak Marc Gravell'in cevabının gösterdiği gibi, [MethodImpl (MethodImplOptions.Synchronized)] ek açıklamasını kullanarak yöntem düzeyinde senkronize edebilirsiniz.
MindJuice

1
Java's synchronizedon yöntemi temelde synchronized (this.getClass())C # benzer olmaz lock(typeof(this))mı?
Sri Harsha Chilakapati

2
@SriHarshaChilakapati sadece kısmen doğrudur, java'nın synchronizedbir yöntem üzerindeki anahtar kelimesi daha çok şöyledir:, synchronized(this)sadece davrandığı statik bir yöntemde synchronized(class).
bvdb

6

Dikkat edin, tam yollarla çizgi: [MethodImpl(MethodImplOptions.Synchronized)]şöyle görünmelidir

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]


1
ya da sadece kullanabilirsinizusing System.Runtime.CompilerServices;
aloisdg taşınma codidact.com

Bu açıklamayı henüz birkaç gün veya haftadan fazla olmamak üzere C # programladıktan sonra, ifadeleri kullanarak otomatik olarak ekleme hakkında henüz bilmediğimde yazdım ve bu 3 upvotes hakkında şaşırdım.
Traubenfuchs

1
En az 3 geliştiriciye yardım ettiniz ve bu güzel :)
aloisdg, codidact.com'a taşınıyor

5

Kullanabilirsiniz lock yerine ifadeyi . Bunun sadece ikinci sürümün yerini alabileceğini düşünüyorum. Ayrıca, hem unutmayın synchronizedve lockihtiyaç bir nesne üzerinde çalışmak üzere.

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.