자세 한 설명 c\#스 레 드 동기 화

1.스 레 드 동기 화 개요
앞의 글 은 다 중 스 레 드 를 만들어 서 프로그램 에 더 잘 응답 할 수 있 도록 하 는 것 을 말 합 니 다.그러나 우리 가 여러 스 레 드 를 만 들 었 을 때 여러 스 레 드 가 공 유 된 자원 에 동시에 접근 하 는 상황 이 존재 합 니 다.이런 상황 에서 우 리 는 스 레 드 동기 화 를 사용 해 야 합 니 다.스 레 드 동기 화 는 데이터(공유 자원)의 손상 을 방지 할 수 있 습 니 다.
그러나 우 리 는 응용 프로그램 을 설계 할 때 라인 동기 화 를 최대한 피해 야 한다.왜냐하면 라인 동기 화 에 문제 가 생 길 수 있 기 때문이다.
1.그것 의 사용 은 비교적 번거롭다.여러 스 레 드 가 동시에 접근 하 는 데 이 터 를 추가 코드 로 둘러싸 고 스 레 드 동기 화 자 물 쇠 를 가 져 오고 풀 어야 하기 때문에 코드 블록 에서 자 물 쇠 를 가 져 오 는 것 을 잊 으 면 데이터 가 손 상 될 수 있 습 니 다.
2.스 레 드 동기 화 를 사용 하면 성능 에 영향 을 줄 수 있 습 니 다.자 물 쇠 를 가 져 오고 방출 하 는 데 시간 이 걸 릴 것 입 니 다.어떤 스 레 드 가 먼저 자 물 쇠 를 가 져 올 지 결정 할 때 CPU 가 조 화 를 이 루어 야 하기 때 문 입 니 다.이런 추가 작업 을 하면 성능 에 영향 을 줄 수 있 습 니 다.
3.스 레 드 가 한 번 에 한 스 레 드 만 자원 에 접근 할 수 있 기 때문에 스 레 드 를 막 을 수 있 고 스 레 드 를 막 으 면 더 많은 스 레 드 가 생 성 될 수 있 습 니 다.그러면 CPU 는 더 많은 스 레 드 를 조정 해 야 할 수도 있 고 성능 에 도 영향 을 줄 수 있 습 니 다.
따라서 실제 디자인 에서 스 레 드 동기 화 를 최대한 피해 야 하기 때문에 우 리 는 공유 데이터,예 를 들 어 정적 필드 를 사용 하 는 것 을 피해 야 한다.
2.스 레 드 동기 화 사용
2.1 자물쇠 사용 성능 에 대한 영향
위 에서 이미 말 했 듯 이 자 물 쇠 를 사용 하면 성능 에 영향 을 미 칠 수 있다.다음은 자 물 쇠 를 사용 하거나 자 물 쇠 를 사용 하지 않 을 때 소모 되 는 시간 을 비교 하여 이 점 을 설명 한다.

using System;
using System.Diagnostics;
using System.Threading;

namespace InterlockedSample
{
  //                 
  //                
  class Program
  {
    static void Main(string[] args)
    {
      int x = 0;
      //      500 
      const int iterationNumber = 5000000; 
      //        
      // StartNew       Stopwatch        ,           ,          。
      Stopwatch sw = Stopwatch.StartNew();
      for (int i = 0; i < iterationNumber; i++)
      {
        x++;
      }

      Console.WriteLine("Use the all time is :{0} ms", sw.ElapsedMilliseconds);

      sw.Restart();
      //       
      for (int i = 0; i < iterationNumber; i++)
      {
        Interlocked.Increment(ref x);
      }

      Console.WriteLine("Use the all time is :{0} ms", sw.ElapsedMilliseconds);
      Console.Read();
    }
  }
}
운행 결과(이것 은 내 컴퓨터 에서 운행 한 결과)결과 에서 알 수 있 듯 이 자 물 쇠 를 넣 은 운행 속도 가 많이 느 려 졌 다(11 배 197/18).

2.2 Interlocked 스 레 드 동기 화 실현
Interlocked 류 는 여러 스 레 드 가 공유 하 는 변 수 를 위해 원자 조작 을 제공 합 니 다.우리 가 다 중 스 레 드 에서 하나의 정 수 를 증가 시 킬 때 스 레 드 동기 화 를 실현 해 야 합 니 다.
변수 추가 작업(+연산 자)은 원자 작업 이 아니 기 때문에 다음 절 차 를 실행 해 야 합 니 다.
1)인 스 턴 스 변수의 값 을 레지스터 에 불 러 옵 니 다.
2)이 값 을 증가 하거나 감소 합 니 다.
3)인 스 턴 스 변수 에 이 값 을 저장 합 니 다.
Interlocked.increment 방법 을 사용 하지 않 으 면 스 레 드 는 앞의 두 단 계 를 실행 한 후에 앞 설 수 있 습 니 다.그 다음 에 다른 스 레 드 에서 모든 세 단 계 를 실행 합 니 다.이때 첫 번 째 스 레 드 는 변수의 값 을 인 스 턴 스 변수 에 저장 하지 않 았 고 다른 스 레 드 는 인 스 턴 스 변 수 를 레지스터 에 불 러 와 읽 을 수 있 습 니 다.(이때 불 러 온 값 은 변 하지 않 았 습 니 다)그래서 우리 가 예상 한 결과 가 아 닙 니 다.이러한 해석 이 Interlocked.Incrediment 방법 과 원자 성 조작 을 잘 이해 하 는 데 도움 이 될 것 이 라 고 믿 습 니 다.
다음은 코드 를 통 해 자 물 쇠 를 추가 하 는 것 과 자 물 쇠 를 추가 하지 않 는 것 의 차 이 를 보 여 줍 니 다.(자 물 쇠 를 추가 하면 성능 에 영향 을 줄 수 있 습 니 다.여기 서 자 물 쇠 를 추가 하여 스 레 드 동기 화 문 제 를 해결 하고 우리 가 기대 하 는 결 과 를 얻 을 수 있 습 니 다)
잠 금 이 없 는 경우:

class Program
  {
    static void Main(string[] args)
    {   for (int i = 0; i < 10; i++)
      {
        Thread testthread = new Thread(Add);
        testthread.Start();
      }

      Console.Read();
    }

    //     
    public static int number = 1;

    public static void Add()
    {
      Thread.Sleep(1000);
      Console.WriteLine("the current value of number is:{0}", ++number);
    }
}
실행 결과(컴퓨터 에 따라 실행 가능 한 결 과 는 나의 것 과 다 르 지만 모두 예상 치 못 한 결 과 를 얻 었 습 니 다):

이러한 문 제 를 해결 하기 위해 서 우 리 는 Interlocked.Incrediment 방법 을 사용 하여 원자의 자체 증가 조작 을 실현 할 수 있다.
코드 는 간단 합 니 다.++number 를 Interlocked.Increment(ref number)로 바 꾸 면 우리 가 예상 한 결 과 를 얻 을 수 있 습 니 다.여기 서 코드 와 실행 결 과 는 붙 이지 않 습 니 다.
어쨌든 Interlocked 클래스 의 방법 은 원자 읽 기와 쓰기 동작 을 수행 합 니 다.
2.3 Monitor 스 레 드 동기 화 실현
위의 상황 에 대해 서도 Monitor.Enter 와 Monitor.Exit 방법 을 통 해 스 레 드 동기 화 를 실현 할 수 있 습 니 다.C\#에서 lock 키 워드 를 통 해 간단 한 문법(lock 은 Monitor.Enter 와 Monitor.Exit 방법 으로 이해 할 수 있 는 문법 사탕)을 제공 합 니 다.코드 도 간단 합 니 다.

using System;
using System.Threading;

namespace MonitorSample
{
  class Program
  {
    static void Main(string[] args)
    {
      for (int i = 0; i < 10; i++)
      {
        Thread testthread = new Thread(Add);
        testthread.Start();
      }

      Console.Read();
    }

    //     
    public static int number = 1;

    public static void Add()
    {
      Thread.Sleep(1000);
      //     
      Monitor.Enter(number);

      Console.WriteLine("the current value of number is:{0}", number++);

      //            。
      Monitor.Exit(number);
    }
  }
}
운행 결 과 는 당연히 우리 가 기대 하 는 것 이다.

Monitor 류 에 서 는 또 다른 몇 가지 방법 이 소개 되 어 있 습 니 다.다만 주 의 를 끌 수 있 도록 하나의 Wait 방법 은 Wait 방법의 역할 이 뚜렷 합 니 다.어떤 대상 의 자 물 쇠 를 풀 어 다른 스 레 드 가 이 대상 을 잠 그 고 방문 할 수 있 도록 하 는 것 입 니 다.두 번 째 는 TryEnter 방법 입 니 다.이 방법 은 Enter 방법 과 주요 한 차이 점 은 현재 스 레 드 를 막 을 지 여부 입 니 다.한 대상 이 Enter 방법 으로 자 물 쇠 를 가 져 올 때 Exit 방법 으로 자 물 쇠 를 풀 지 않 습 니 다.다른 스 레 드 가 Enter 를 통 해 자 물 쇠 를 얻 으 려 고 할 때 이 스 레 드 는 막 힐 것 입 니 다.다른 스 레 드 가 자 물 쇠 를 풀 때 까지 TryEnter 는 스 레 드 를 막 지 않 습 니 다.구체 적 인 코드 는 쓰 지 않 겠 습 니 다.
2.4 ReaderWriterLock 스 레 드 동기 화 실현
만약 에 우리 가 공유 자원 에 대해 여러 번 읽 어야 할 때 앞에서 말 한 클래스 로 이 루어 진 동기 화 잠 금 은 하나의 스 레 드 만 허용 하고 모든 스 레 드 가 막 힐 것 입 니 다.그러나 이런 상황 에서 켄 은 다른 스 레 드 를 막 을 필요 가 없습니다.동시에 실행 하도록 해 야 합 니 다.왜냐하면 우 리 는 이 때 읽 기 작업 만 하기 때 문 입 니 다.이 때 Reader WriterLock 클래스 를 통 해 읽 기와 병행 을 잘 할 수 있 습 니 다.
데모 코드:

using System;
using System.Collections.Generic;
using System.Threading;

namespace ReaderWriterLockSample
{
  class Program
  {
    public static List<int> lists = new List<int>();

    //       
    public static ReaderWriterLock readerwritelock = new ReaderWriterLock();
    static void Main(string[] args)
    {
      //          
      Thread t1 = new Thread(Write);
      t1.Start();
      //   10       
      for (int i = 0; i < 10; i++)
      {
        Thread t = new Thread(Read);
        t.Start();
      }

      Console.Read();

    }

    //     
    public static void Write()
    {
      //      , 10     。
      readerwritelock.AcquireWriterLock(10);
      Random ran = new Random();
      int count = ran.Next(1, 10);
      lists.Add(count);
      Console.WriteLine("Write the data is:" + count);
      //      
      readerwritelock.ReleaseWriterLock();
    }

    //     
    public static void Read()
    {
      //      
      readerwritelock.AcquireReaderLock(10);

      foreach (int li in lists)
      {
        //        
        Console.WriteLine(li);
      }

      //      
      readerwritelock.ReleaseReaderLock();
    }
  }
}
실행 결과:

3.총화
본 고 는 주로 다 중 스 레 드 동기 화 문 제 를 어떻게 실현 하 는 지 소개 하고 스 레 드 동기 화 를 통 해 공유 데이터 의 손상 을 방지 할 수 있 으 나 자 물 쇠 를 얻 는 과정 에서 성능 손실 이 있 기 때문에 디자인 응용 과정 에서 스 레 드 동기 화 사용 을 최대한 줄인다.상호 배척(Mutex),신 호 량(Semaphore),사건 구 조 를 소개 해 야 하 는데 편폭 때문에 여러분 의 읽 기 에 영향 을 줄 까 봐 나머지 내용 은 뒤에 소개 해 드 리 겠 습 니 다.
이상 은 c\#스 레 드 동기 화 에 대한 상세 한 내용 입 니 다.c\#스 레 드 동기 화 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기