Спільна пам’ять у C#

Спільна пам'ять у C

У C# спільна пам'ять означає пам'ять, яка доступна для кількох компонентів або потоків у межах одного додатка. Цей термін часто використовується в контексті статичних полів, доменів додатків та мультитредінгу. Спільна пам'ять дозволяє ефективно обмінюватися даними, але вимагає ретельного керування, щоб уникнути проблем, таких як умови гонки.

1. Спільна пам'ять у статичних полях

У C# статичні поля зберігаються в спільній пам'яті, що означає:

  • Статичне поле належить самій класу, а не конкретному екземпляру.
  • Усі екземпляри класу ділять ту саму копію статичного поля.
  • Статичні поля зберігаються в кучі, але вони виділяються лише один раз для додатка (або AppDomain).

Приклад спільної пам'яті в статичних полях

class MyClass  
{  
 public static int SharedCount = 0; // Спільна пам'ять для всіх екземплярів  
}  

class Program  
{  
 static void Main()  
 {  
 MyClass.SharedCount++;  
 Console.WriteLine(MyClass.SharedCount); // Виведеться: 1  
 MyClass.SharedCount++;  
 Console.WriteLine(MyClass.SharedCount); // Виведеться: 2  
 }  
}
  • Поле SharedCount інкрементується всіма екземплярами MyClass, що відображає спільну природу статичних полів.

2. Спільна пам'ять у мультитредінгу

Коли кілька потоків ділять одну й ту ж пам'ять (наприклад, доступ до тих самих статичних полів або властивостей класу), це може призвести до проблем з паралельним виконанням, таких як умови гонки або пошкодження даних.

Приклад: Спільна пам'ять з потоками

using System;  
using System.Threading;  

class Counter  
{  
 public static int Count = 0; // Спільна пам'ять  
}  
class Program  
{  
 static void Main()  
 {  
 Thread t1 = new Thread(() => { for (int i = 0; i < 1000; i++) Counter.Count++; });  
 Thread t2 = new Thread(() => { for (int i = 0; i < 1000; i++) Counter.Count++; });  
 t1.Start();  
 t2.Start();  
 t1.Join();  
 t2.Join();  
 Console.WriteLine(Counter.Count); // Може бути не 2000 через умови гонки  
 }  
}

У цьому прикладі:

  • Обидва потоки змінюють статичне поле Counter.Count, яке знаходиться в спільній пам'яті.
  • Без належної синхронізації результат може бути неконсистентним.

Рішення: Синхронізація

Ви можете використовувати блокування для захисту спільної пам'яті від одночасного доступу:

class Counter  
{  
 private static object lockObj = new object();  
 public static int Count = 0;  

 public static void Increment()  
 {  
 lock (lockObj)  
 {  
 Count++;  
 }  
 }  
}

3. Домен додатків і спільна пам'ять

  • У попередніх версіях .NET (до .NET Core) домен додатка (AppDomain) забезпечував ізоляцію між різними додатками, що працюють в одному процесі.
  • Статичні поля були спільними в межах одного AppDomain, але ізольовані між різними AppDomains.

У .NET Core та .NET 5+ AppDomains були замінені на більш легкі механізми, такі як AssemblyLoadContext.

4. Спільна пам'ять у паралельному програмуванні

У паралельному програмуванні (наприклад, використовуючи Tasks, PLINQ або ThreadPool) спільна пам'ять повинна ретельно керуватися, щоб уникнути пошкодження даних. Інструменти, такі як конкурентні колекції або взаємно блокуючі операції, можуть допомогти.

Приклад: Використання Interlocked для потокобезпечної спільної пам'яті

using System;  
using System.Threading;  

class Counter  
{  
 public static int Count = 0;  
}  
class Program  
{  
 static void Main()  
 {  
 Thread t1 = new Thread(() =>  
 {  
 for (int i = 0; i < 1000; i++)  
 Interlocked.Increment(ref Counter.Count); // Потокобезпечний інкремент  
 });  
 Thread t2 = new Thread(() =>  
 {  
 for (int i = 0; i < 1000; i++)  
 Interlocked.Increment(ref Counter.Count); // Потокобезпечний інкремент  
 });  
 t1.Start();  
 t2.Start();  
 t1.Join();  
 t2.Join();  
 Console.WriteLine(Counter.Count); // Виведеться: 2000  
 }  
}

## Спільна пам'ять у міжпроцесорній комунікації (IPC)

Якщо кілька процесів повинні ділити пам'ять:

- Можна використовувати **файли з відображенням пам'яті**.
- Це дозволяє процесам читати та записувати в одну й ту саму область пам'яті.

### Приклад: Спільна пам'ять з файлами з відображенням пам'яті

using System;
using System.IO.MemoryMappedFiles;

class Program
{
static void Main()
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("SharedMemory", 1024))
{
using (var accessor = mmf.CreateViewAccessor())
{
accessor.Write(0, 42); // Запис у спільну пам'ять
int value = accessor.ReadInt32(0); // Читання зі спільної пам'яті
Console.WriteLine(value); // Виведе: 42
}
}
}
}
```

Ключові моменти

  1. Статичні поля:
  • Спільні для всіх екземплярів класу.
  • Зберігаються в одному місці в купі.

2. Безпека потоків:

  • Спільна пам'ять між потоками потребує синхронізації (наприклад, блокування або взаємно блокуючі операції).

3. Міжпроцесорна комунікація (IPC):

  • Файли з відображенням пам'яті дозволяють спільну пам'ять між процесами.

Перекладено з: Shared Memory in C#

Leave a Reply

Your email address will not be published. Required fields are marked *