
C# Interlocked (개발자를 위한 작동 원리)
멀티스레드 응용 프로그램을 다룰 때, 스레드 안전성을 보장하는 것은 경쟁 조건 및 데이터 손상을 방지하는 데 있어 중요한 요소가 됩니다. IronPDF로 PDF를 처리하는 세계에서도 이 문제는 다르지 않습니다. PDF를 생성, 조작 또는 결합하든, 이러한 작업을 동시에 수행하면 적절한 동기화가 유지되지 않을 경우 예기치 않은 결과를 초래할 수 있습니다. 이러한 상황에서 C#의 Interlocked 클래스가 작동하여 멀티스레드 환경에서 스레드 안전 작업을 보장하는 간단하고 효율적인 방법을 제공합니다.
C# Interlocked 클래스란 무엇입니까?
C#에서 Interlocked 클래스는 여러 스레드에서 공유되는 변수에 대한 원자적 작업을 제공합니다. 이는 한 스레드의 작업이 다른 스레드에 의해 방해되지 않도록 보장하며, 작업이 통제되고 일관된 방식으로 수행될 필요가 있을 때 필수적입니다. 반면에 IronPDF는 .NET 개발자가 PDF를 생성, 편집 및 조작할 수 있도록 하는 강력한 라이브러리입니다.
Interlocked를 통해 스레드 안전성을 보장하고 IronPDF로 PDF 작업을 수행하면 동시 프로그래밍에서 PDF 작업을 처리할 수 있는 강력한 솔루션을 얻을 수 있습니다. 그러나 이것이 어떻게 작동하며 왜 이것이 중요할까요? IronPDF 처리에서 Interlocked의 역할을 더 깊이 이해합시다.
IronPDF: 올인원 C# PDF 라이브러리

IronPDF는 PDF 생성 및 조작을 위해 C# 및 .NET 응용 프로그램과 원활하게 작동하도록 설계된 다재다능하고 기능이 풍부한 라이브러리입니다. 그의 단순성과 성능 덕분에 PDF 작업을 자동화해야 하는 개발자에게 인기 있는 선택입니다. 아래는 IronPDF의 몇 가지 주요 기능입니다:
- HTML을 PDF로 변환: IronPDF를 사용하면 HTML 콘텐츠를 고품질 PDF로 변환할 수 있습니다. 이는 보고서, 청구서, HTML로 렌더링되는 모든 콘텐츠를 작성하는 데 특히 유용합니다.
- PDF 편집 및 조작: 병합, 분할 또는 페이지 추출을 통해 기존 PDF 문서를 조작할 수 있습니다. 게다가, IronPDF는 PDF 내의 콘텐츠를 수정하여 텍스트, 이미지 또는 주석을 추가할 수 있게 합니다.
- PDF 양식 및 필드: IronPDF는 PDF 양식을 다루고, 프로그래밍 방식으로 양식 필드를 채우는 것을 지원합니다. 이는 설문 조사, 신청서 및 계약과 같은 문서를 자동으로 생성할 수 있는 이상적인 솔루션입니다.
- 디지털 서명: 문서 거래가 중요한 법적 및 금융 부문과 같은 산업에 꼭 필요한 기능인 안전한 서명으로 PDF를 디지털 서명할 수 있는 기능을 제공합니다.
이러한 기능을 활용함으로써 IronPDF는 개발자가 PDF 워크플로를 효율적으로 생성, 관리, 자동화하도록 도우며, 동시에 고품질의 결과를 보장합니다. 동적 HTML 콘텐츠를 다루거나 기존 문서를 조작하든, IronPDF는 PDF 관련 작업을 간소화하는 데 필요한 도구를 제공합니다.
IronPDF 처리에 Interlocked를 사용하는 이유는 무엇일까요?
스레드 안전성 및 동시성
멀티스레드 응용 프로그램에서는 여러 스레드가 동시에 공유 데이터를 접근하고 수정하려고 할 수 있습니다. 적절한 동기화 없이 이는 두 스레드가 동시에 같은 데이터를 업데이트하려는 경쟁 조건과 같은 문제를 일으킬 수 있습니다. 이는 예측할 수 없는 결과와 디버깅하기 어려운 오류를 초래할 수 있습니다.
Interlocked 클래스는 이러한 동시 작업이 원자적으로 처리되도록 보장합니다. 즉, Interlocked를 사용하여 객체 값을 수정할 때, 변경은 하나의 단일, 중단할 수 없는 작업으로 발생하며, 이는 경쟁 조건의 위험을 제거합니다.
IronPDF의 맥락에서, 여러 소스를 통해 PDF를 생성하거나 콘텐츠를 편집하거나 페이지를 추가하는 등 여러 PDF 처리 작업들이 병렬 처리에 이상적입니다. 동기화 없이 이러한 작업을 동시에 실행하면 PDF 파일이 손상되거나 처리 중 오류가 발생할 수 있습니다. Interlocked를 사용하면 멀티스레드 환경에서도 이러한 작업이 안전하게 유지됩니다.
Interlocked와 다양한 데이터 타입 사용하기
다양한 데이터 타입의 변수를 다루면서, Interlocked는 동시 업데이트를 안전하게 관리하는 데 사용할 수 있습니다. 여러분이 접할 수 있는 데이터 타입을 탐색해 봅시다:
- 부동 소수점 값: Interlocked.CompareExchange 메소드는 참조 타입이 작업에 필요할 때 부동 소수점 값과 함께 사용할 수 있습니다.
- 원래 값: 업데이트를 수행할 때, 변경을 하기 전 원래 값을 작업하는 것이 스레드 작업에서 일관성을 보장하는 데 중요합니다.
- 공용 정적 클래스: Interlocked 작업을 캡슐화하는 공용 정적 클래스를 만들어 코드를 더 모듈화하고 유지 관리하기 쉽게 만들 수 있습니다.
- 더블 값: Interlocked는 직접적으로 더블 값을 지원하지 않습니다. 더블은 정수 타입이 아니며 원자적 작업은 정수에 최적화되어 있습니다. double 값에 대한 원자적 연산이 필요할 경우, long 값을 사용하고 double과 long 값 사이를 수동으로 변환하여 해결할 수 있습니다.
public static class ThreadSafeOperations
{
private static int counter = 0;
public static void IncrementCounter()
{
// Safely increment the counter using Interlocked
Interlocked.Increment(ref counter);
}
}Public Module ThreadSafeOperations
Private counter As Integer = 0
Public Sub IncrementCounter()
' Safely increment the counter using Interlocked
Interlocked.Increment(counter)
End Sub
End ModuleIronPDF에서 Interlocked를 사용할 때
여러 스레드가 공유 리소스를 다루는 모든 상황에서 Interlocked를 사용해야 합니다. 예는 다음과 같습니다:
- PDF 생성 시 페이지 번호 추적.
- 여러 스레드에 의해 접근되고 수정되는 카운터 또는 목록 관리.
이러한 작업에 Interlocked를 사용하면 업데이트가 스레드 안전성을 보장하고 충돌을 방지하며 데이터 무결성을 보장합니다.
IronPDF로 Interlocked 구현하기
Basic Usage of Interlocked in C#
Interlocked 클래스는 변수에 대한 원자적 연산을 수행할 수 있는 여러 메소드를 제공합니다. 예를 들어:
- Add: 두 정수를 더하여 결과를 변수에 저장합니다.
- CompareExchange: 두 값을 비교하여 같으면 그 중 하나의 값을 교체합니다.
- Increment: int 값을 1 증가시키고 새 값을 반환합니다.
- Decrement: int 값을 1 감소시키고 새 값을 반환합니다.
예를 들어, 멀티스레드 환경에서 공유 카운터를 안전하게 증가시킬 필요가 있을 때 Interlocked.Increment를 사용하세요:
int counter = 0;
Interlocked.Increment(ref counter);Dim counter As Integer = 0
Interlocked.Increment(counter)이렇게 하면 여러 스레드가 동시에 수정하는 경우에도 카운터가 안전하게 증가하도록 보장됩니다.
IronPDF와 C# Interlocked를 이용한 스레드 안전한 PDF 생성
멀티스레드 상황에서 IronPDF와 함께 Interlocked를 사용한 실용적인 예제를 살펴봅시다. 예를 들어, 병렬 스레드에서 PDF 파일을 생성하고 각 스레드에 고유 식별자나 페이지 번호가 필요합니다.
이를 구현하는 방법은 다음과 같습니다:
using IronPdf;
using System;
using System.Threading;
using System.Collections.Generic;
class Program
{
static int pageCount = 0;
static readonly object lockObject = new object(); // Object for locking
static void Main()
{
var threads = new Thread[5];
List<PdfDocument> pdfList = new List<PdfDocument>();
// Create threads for parallel PDF generation
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(() => GeneratePdf(pdfList));
threads[i].Start();
}
// Wait for all threads to complete
foreach (var thread in threads)
{
thread.Join();
}
// Merge all the generated PDFs
PdfDocument finalPdf = pdfList[0]; // Start with the first document
// Merge remaining PDFs into finalPdf
for (int i = 1; i < pdfList.Count; i++)
{
finalPdf = PdfDocument.Merge(finalPdf, pdfList[i]);
}
// Save the merged PDF
finalPdf.SaveAs("MergedGeneratedPDF.pdf");
Console.WriteLine("All PDFs merged and saved successfully.");
}
static void GeneratePdf(List<PdfDocument> pdfList)
{
// Use ChromePdfRenderer instead of HtmlToPdf
ChromePdfRenderer renderer = new ChromePdfRenderer();
// Use Interlocked to ensure unique page number per thread and using a "ref object" to reference the pageCount object
int pageNum = Interlocked.Increment(ref pageCount);
// Generate a PDF page using ChromePdfRenderer
var pdfPage = renderer.RenderHtmlAsPdf($"Page {pageNum} generated by thread {Thread.CurrentThread.ManagedThreadId}");
// Add generated PDF page to the list (thread-safe)
lock (lockObject) // Ensure thread-safety when adding to shared list
{
pdfList.Add(pdfPage);
}
string fileName = $"GeneratedPDF_{pageNum}.pdf";
pdfPage.SaveAs(fileName);
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} generated: {fileName}");
}
}Imports IronPdf
Imports System
Imports System.Threading
Imports System.Collections.Generic
Module Program
Private pageCount As Integer = 0
Private ReadOnly lockObject As New Object() ' Object for locking
Sub Main()
Dim threads(4) As Thread
Dim pdfList As New List(Of PdfDocument)()
' Create threads for parallel PDF generation
For i As Integer = 0 To threads.Length - 1
threads(i) = New Thread(Sub() GeneratePdf(pdfList))
threads(i).Start()
Next
' Wait for all threads to complete
For Each thread As Thread In threads
thread.Join()
Next
' Merge all the generated PDFs
Dim finalPdf As PdfDocument = pdfList(0) ' Start with the first document
' Merge remaining PDFs into finalPdf
For i As Integer = 1 To pdfList.Count - 1
finalPdf = PdfDocument.Merge(finalPdf, pdfList(i))
Next
' Save the merged PDF
finalPdf.SaveAs("MergedGeneratedPDF.pdf")
Console.WriteLine("All PDFs merged and saved successfully.")
End Sub
Sub GeneratePdf(pdfList As List(Of PdfDocument))
' Use ChromePdfRenderer instead of HtmlToPdf
Dim renderer As New ChromePdfRenderer()
' Use Interlocked to ensure unique page number per thread and using a "ref object" to reference the pageCount object
Dim pageNum As Integer = Interlocked.Increment(pageCount)
' Generate a PDF page using ChromePdfRenderer
Dim pdfPage = renderer.RenderHtmlAsPdf($"Page {pageNum} generated by thread {Thread.CurrentThread.ManagedThreadId}")
' Add generated PDF page to the list (thread-safe)
SyncLock lockObject ' Ensure thread-safety when adding to shared list
pdfList.Add(pdfPage)
End SyncLock
Dim fileName As String = $"GeneratedPDF_{pageNum}.pdf"
pdfPage.SaveAs(fileName)
Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} generated: {fileName}")
End Sub
End Module코드 설명
이 C# 프로그램은 스레드를 사용하여 병렬로 여러 PDF를 생성한 후, IronPDF를 사용하여 하나의 PDF로 병합합니다.
- 멀티스레딩: PDF 생성을 동시 처리하기 위해 5개의 스레드가 생성됩니다. 각 스레드는 Interlocked.Increment를 사용하여 고유한 페이지 번호를 받습니다.
- 스레드 안전성: 병합할 때 목록에 PDF를 추가하는 과정에서 경쟁 조건을 방지하기 위해 공유 pdfList에 대한 접근은 lock 문을 사용해 동기화됩니다.
- PDF 병합: 모든 스레드가 완료된 후, pdfList의 PDF는 차례로 PdfDocument.Merge를 사용해 병합되며, 최종 PDF가 저장됩니다.
- 동기화: 메인 스레드는 merge가 진행되기 전에 모든 스레드가 완료되기를 thread.Join()을 사용해 기다립니다.
콘솔 출력

PDF 출력

이것이 왜 스레드 안전한지
- 스레드 안전한 목록 수정: lock을 사용하면 공유 pdfList의 수정이 안전하며 여러 스레드가 동시에 목록에 추가하여 경쟁 조건을 발생시키는 것을 방지합니다.
- 비동기 코드 불필요: 이 코드는 async/await가 필요하지 않습니다. 왜냐하면 작업이 순차적으로 진행되고 장시간 동안 I/O 또는 네트워크 호출을 포함하지 않기 때문입니다. 여기서 주요 관심사는 공유 데이터(목록)에 대한 접근이 적절히 동기화되는 것입니다.
오류 처리 및 성능 고려사항
멀티 스레딩 코드 작업 시 오류 처리 및 성능 최적화가 중요합니다.
- 오류 처리: Interlocked는 스레드 안전성을 보장하지만 PDF 생성 논리에서 발생할 수 있는 잠재적인 오류를 여전히 관리해야 합니다. try-catch 블록을 사용해 예외를 우아하게 처리할 수 있습니다:
try
{
finalPdf.SaveAs(fileName);
}
catch (Exception ex)
{
Console.WriteLine($"Error generating PDF: {ex.Message}");
}Try
finalPdf.SaveAs(fileName)
Catch ex As Exception
Console.WriteLine($"Error generating PDF: {ex.Message}")
End Try- 성능 고려사항: Interlocked는 원자적 연산에 최적화되어 있지만, 과도한 동기화는 오버헤드를 발생시킬 수 있습니다. 동시 작업의 볼륨이 큰 경우, 동기화를 가장 중요한 공유 변수로 최소화하여 경쟁을 줄여야 합니다.
결론
스레드 안전성은 멀티 스레딩 애플리케이션에서 중요하며, 특히 카운터나 목록 같은 공유 리소스를 다룰 때 매우 중요합니다. PDF 생성이나 조작에 IronPDF를 사용할 때, Interlocked를 통합하면 작업이 스레드 안전하고 신뢰할 수 있도록 보장합니다.
IronPDF와 함께 Interlocked를 사용함으로써, .NET 개발자는 데이터의 무결성을 유지하면서 PDF 처리 워크플로우를 효율적으로 확장할 수 있습니다. 보고서를 생성하거나 문서를 병합하거나 병렬로 복잡한 PDF 조작을 수행할 때, Interlocked는 일관성을 유지하고 경쟁 조건을 피하는 데 도움이 됩니다.
이러한 모범 관행을 통해 IronPDF의 기능을 충분히 활용할 수 있으며, 멀티 스레드 PDF 워크플로우가 효율적이고 견고하게 유지되도록 할 수 있습니다. IronPDF를 오늘 시작하여 강력한 PDF 생성 및 조작 기능을 직접 경험하십시오!

제이콥 멜러는 Iron Software의 최고 기술 책임자(CTO)이자 C# PDF 기술을 개척한 선구적인 엔지니어입니다. Iron Software의 핵심 코드베이스를 최초로 개발한 그는 창립 초기부터 회사의 제품 아키텍처를 설계해 왔으며, CEO인 캐머런 리밍턴과 함께 회사를 NASA, 테슬라, 그리고 전 세계 정부 기관에 서비스를 제공하는 50명 이상의 직원을 보유한 기업으로 성장시켰습니다.
관련 기사


