คีย์เวิร์ดที่ซิงโครไนซ์ของ Java เวอร์ชัน C # หรือไม่


313

c # มีคีย์เวิร์ด "ซิงโครไนซ์" ของ Java เวอร์ชันของตัวเองหรือไม่

เช่นใน java มันสามารถระบุได้ทั้งฟังก์ชั่นวัตถุหรือบล็อกของรหัสเช่น:

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

หรือ

public void doImportantStuff() {
   // trivial stuff

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

3
รูปแบบบล็อกต้องมีการอ้างอิงเพื่อล็อค ในรูปแบบวิธีการล็อควัตถุโดยปริยายนี้ (หรือ Class [this.class ไม่ใช่ getClass ()] สำหรับวิธีการคงที่ แต่ไม่ล็อคใน Classes)
Tom Hawtin - tackline

1
ยังไม่ได้รับการป้องกัน? ฉันมาที่นี่เสมอเพราะจำ[MethodImpl(MethodImplOptions.Synchronized)]สายไม่ได้
Bitterblue

1
ฉันคิดว่าข้อมูลโค้ดที่สองของคุณจะไม่รวบรวม - มันจำเป็นต้องซิงโครไนซ์กับบางสิ่ง
PoweredByRice

คำตอบ:


466

First - คลาสส่วนใหญ่ไม่จำเป็นต้องเป็น thread-safe ใช้YAGNI : ใช้ความปลอดภัยของเธรดเท่านั้นเมื่อคุณรู้ว่าคุณกำลังใช้งานจริง (และทดสอบ)

สำหรับสิ่งที่ระดับวิธีมี[MethodImpl]:

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

สิ่งนี้สามารถใช้กับ accessors (คุณสมบัติและเหตุการณ์):

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

โปรดทราบว่าเหตุการณ์ที่คล้ายฟิลด์จะซิงโครไนซ์โดยค่าเริ่มต้นในขณะที่คุณสมบัติที่ใช้งานอัตโนมัติจะไม่ :

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

โดยส่วนตัวแล้วฉันไม่ชอบการนำไปใช้MethodImplเพราะมันล็อคthisหรือtypeof(Foo)- ซึ่งขัดกับแนวปฏิบัติที่ดีที่สุด ตัวเลือกที่ต้องการคือการใช้ล็อคของคุณเอง:

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

โปรดทราบว่าสำหรับเหตุการณ์ที่คล้ายฟิลด์การดำเนินการล็อกขึ้นอยู่กับคอมไพเลอร์ ในคอมไพเลอร์ Microsoft รุ่นเก่ามันเป็นlock(this)/ lock(Type)- อย่างไรก็ตามในคอมไพเลอร์ล่าสุดจะใช้Interlockedการอัพเดตดังนั้นเธรดที่ปลอดภัยโดยไม่มีส่วนที่น่ารังเกียจ

สิ่งนี้อนุญาตให้ใช้แบบละเอียดมากขึ้นและอนุญาตให้ใช้Monitor.Wait/ Monitor.Pulseetc เพื่อสื่อสารระหว่างเธรด

ที่เกี่ยวข้องกับรายการบล็อก (ต่อมาเยือน )


@earcam และคำถามของคุณคืออะไร? คำพูดนั้นเป็นความจริง ชั้นเรียนส่วนใหญ่ไม่มีข้อกำหนดว่าจะต้องปลอดภัยต่อเธรดและจะไม่ถูกทดสอบสำหรับความปลอดภัยของเธรดและการมีความปลอดภัยของเธรดจะส่งผลต่อประสิทธิภาพ จำนวนประเภทที่แท้จริงที่ต้องกังวลเกี่ยวกับเธรดมีน้อยมาก - คอลเลกชันที่มีการซิงโครไนซ์มัลติเพล็กเซอร์ที่ตรงกันโดยเจตนา
Marc Gravell

4
ฉันคิดว่าฉันควรจะกล่าวเพียง; "คลาสส่วนใหญ่ไม่จำเป็นต้องปลอดภัยสำหรับเธรด" แต่ "นักพัฒนาทั้งหมดจะต้องทราบพร้อมกัน" ในการหวนกลับฉันเห็นด้วยจำนวนน้อยมาก (และบางสิ่งบางอย่างที่คุณต้องการได้ทันทีในที่เดียวช่วยให้ส่วนใหญ่ของชั้นเรียนเพื่อโต้ตอบกับสภาพแวดล้อมแบบมัลติเธรดของพวกเขาลืมเลือน) หวังว่าฉันจะลบความคิดเห็นที่รวดเร็ว =)
earcam

6
โพสต์บล็อกที่เชื่อมโยงของ Marc มีการติดตามในเดือนมีนาคม 2010 โดยบอกว่าใน. NET 4.0 MethodImplและขณะนี้เหตุการณ์คล้ายฟิลด์จะสร้างรหัสการซิงโครไนซ์ที่ดีและไม่จำเป็นต้องใช้การล็อคของคุณอีกต่อไป
Rory O'Kane

2
แอปพลิเคชั่นส่วนใหญ่ที่ดีเหล่านี้เป็นเว็บที่ให้บริการกับเฟรมเวิร์กที่ต้องใช้อินสแตนซ์หนักและวงจรชีวิตของวัตถุที่ซับซ้อนผ่านการพึ่งพาการฉีด ความคิดเริ่มต้นวันนี้มีแนวโน้มที่จะผิดด้านความปลอดภัยของด้าย
Sheepy

1
@Elazar สายเกินไป แต่สำหรับเร็กคอร์ด: การเปลี่ยนเฟรมเวิร์กคือการเปลี่ยนแปลงหนึ่งบรรทัดสำหรับพวกเขา csproj หากคุณสร้างโดยใช้เท็มเพลตหลัก. net มาตรฐาน / .net - และ. net ปกติพร้อมใช้งาน -targeting อย่างไรก็ตามการใช้เครื่องมือ IDE รอบ ๆ นี้เป็นเรื่องที่แย่มาก - คุณเพียงแค่ต้องรู้ว่าคุณสามารถเปลี่ยนแปลงอะไรได้บ้าง :)
Marc Gravell

56
static object Lock = new object();

lock (Lock) 
{
// do stuff
}

10
คุณแน่ใจหรือไม่ว่าต้องการประกาศวัตถุล็อคของคุณเป็นแบบคงที่ .. ?
serg10

21
แน่นอนว่าทุกเธรดสามารถเข้าถึงได้โดยไม่ต้องผ่านการอ้างอิงรอบ ๆ
Jan Gressmann

33
หากเราอยู่ในบริบทของคำถามของผู้ถามเรากำลังพูดถึงวิธีการแบบอินสแตนซ์ การใช้สแตติกหมายความว่าถ้าเธรด 1 เรียกใช้อินสแตนซ์ 1.DoSomething () และเธรด 2 เรียกใช้อินสแตนซ์ 2.DoSomething การเรียกที่สองจะบล็อกแม้ว่าจะเป็นวัตถุที่แตกต่างกันโดยสิ้นเชิง โทร thread2 ไม่ควรปิดกั้นเว้นแต่มีคนโทร DoSomething บนวัตถุเดียวกัน ไม่ได้บอกว่าคุณคิดผิด แต่การบอกว่ามันเป็นสิ่งสำคัญที่จะต้องเข้าใจถึงผลกระทบของการใช้สเตติกที่นี่เพราะมันอาจทำให้ประสิทธิภาพที่ต่ำโดยการบล็อกทั่วโลกแทนที่จะเป็นพื้นฐานในแต่ละครั้ง
AaronLS

1
@AaronLS ล็อคแบบคงที่ถ้ามีประโยชน์มากเมื่อวัตถุของคุณดำเนินการในขอบเขตที่ใหญ่กว่าตัวมันเอง เกิดขึ้นกับบริการเว็บเสมอ
Thibault D.

4
-1 เนื่องจากนี่เป็นพฤติกรรมที่แตกต่างจาก OP ที่ขอ นี่คือการล็อคคลาสไม่ใช่การล็อกอินสแตนซ์
tster

39

c # มีคีย์เวิร์ด "ซิงโครไนซ์" ของ Java เวอร์ชันของตัวเองหรือไม่

ไม่ใน C # คุณจะต้องlockใช้ทรัพยากรที่คุณต้องการทำงานแบบซิงโครนัสข้ามเธรดแบบอะซิงโครนัสอย่างชัดเจน lockเปิดบล็อก มันไม่ทำงานในระดับวิธี

อย่างไรก็ตามกลไกพื้นฐานนั้นคล้ายคลึงกันตั้งแต่lockทำงานโดยการเรียกใช้Monitor.Enter(และต่อมาMonitor.Exit) ในรันไทม์ Java ทำงานในลักษณะเดียวกันตามที่เอกสารอาทิตย์


3
ไม่มีคำหลัก "เทียบเท่า" แต่ตามคำตอบของ Marc Gravell ด้านบนแสดงคุณสามารถซิงโครไนซ์ที่ระดับวิธีการโดยใช้คำอธิบายประกอบ [MethodImpl (MethodImplOptions.Synchronized)]
MindJuice

1
ตั้งแต่synchronizedวิธีการของ Java เป็นพื้นsynchronized (this.getClass())จะไม่คล้ายกันใน C # เป็นlock(typeof(this))อย่างไร
Sri Harsha Chilakapati

2
@SriHarshaChilakapati ที่ถูกต้องเพียงบางส่วนเท่านั้น, Java ของsynchronizedคำหลักในวิธีการที่มีมากขึ้นเช่น: เฉพาะในวิธีการคงก็จะทำงานเช่นsynchronized(this) synchronized(class)
bvdb

6

จดบันทึกด้วยเส้นทางเต็มบรรทัด: [MethodImpl(MethodImplOptions.Synchronized)]ควรมีลักษณะ

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


1
หรือคุณสามารถใช้using System.Runtime.CompilerServices;
aloisdg กำลังย้ายไปยัง codidact.com

ฉันเขียนความคิดเห็นนั้นเมื่อฉันยังไม่รู้เกี่ยวกับการแทรกโดยอัตโนมัติโดยใช้คำสั่งหลังจากตั้งโปรแกรม C # ไม่เกินสองสามวันหรือสัปดาห์และฉันประหลาดใจเกี่ยวกับ 3 upvotes เหล่านั้น
Traubenfuchs

1
คุณช่วยอย่างน้อย 3 devs และนั่นก็ดี :)
aloisdg ย้ายไป codidact.com

5

คุณสามารถใช้lockคำสั่งแทน ฉันคิดว่านี่สามารถแทนที่รุ่นที่สองเท่านั้น นอกจากนี้โปรดจำไว้ว่าทั้งสองsynchronizedและlockจำเป็นต้องใช้งานบนวัตถุ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.