2011-08-23 2 views
2

지금, 나는 C#에서 멀티 스레딩 및 사용법을 배우고 있습니다. 그래서, 나는 아래와 같은 문제를 겪고 있습니다. (내 간단한 질문에 대해 죄송합니다)스레드 관리 관계 C#

우리는 Producer와 Consumer라는 두 개의 클래스가 있다고 가정합니다. 생산자 작업은 프로그램 실행과 소비자 작업이 소비하면서 그 숫자를 사용하고 프로그램의 끝에서 그것들의 합계를 반환하는 동안 4 개의 숫자를 생성합니다.

소비자 클래스 정의 :

class Consumer 
{ 
    private HoldInteger sharedLocation; 
    private Random randomSleepTime; 

    public Consumer(HoldInteger shared, Random random) 
    { 
     sharedLocation = shared; 
     randomSleepTime = random; 
    } 

    public void Consume() 
    { 
     int sum = 0; 

     for (int i = 1; i <= 4; i++) 
     { 
      Thread.Sleep(randomSleepTime.Next(1, 3000)); 
      sum += sharedLocation.Buffer; 
     } 
    } 
} 

및 생산자 클래스의 정의는 다음과 같습니다 :

class Producer 
{ 
    private HoldInteger sharedLocation; 
    private Random randomSleepTime; 

    public Producer(HoldInteger shared, Random random) 
    { 
     sharedLocation = shared; 
     randomSleepTime = random; 
    } 

    public void Produce() 
    { 
     for (int i = 1; i <= 4; i++) 
     { 
      Thread.Sleep(randomSleepTime.Next(1, 3000)); 
      sharedLocation.Buffer = i; 
     } 
    } 
} 

또한, 우리는 HoldInteger 클래스는 생산자가이 변수 및 소비자 읽기를 작성하는 것이 버퍼 변수를 포함하고있다 그것을 통해서. 나는이 수업을 결합하고 내 주요 방법에 아래 코드 프로그램 :

static void Main(string[] args) 
{ 
    HoldInteger holdInteger = new HoldInteger(); 
    Random random = new Random(); 

    Producer producer = new Producer(holdInteger, random); 

    Consumer consumer = new Consumer(holdInteger, random); 

    Thread producerThread = new Thread(new ThreadStart(producer.Produce)); 
    producerThread.Name = "producer"; 

    Thread consumerThread = new Thread(new ThreadStart(consumer.Consume)); 
    consumerThread.Name = "consumer"; 

    producerThread.Start(); 
    consumerThread.Start(); 
} 

그래서, 내 질문은 How can i manage this relationship With Low Memory and Time Wasting ?

가 있다는 점 유의 하시길 바랍니다 것입니다, 이러한 스레드 관리 코드 HoldInteger 클래스 본문에 배치됩니다.

감사합니다.

답변

4

BlockingQueue, you can find an implementation here으로 HoldInteger 클래스를 대체하고 구현의 이유에 대한 자세한 내용은 check this question입니다. .NET 4.0에는 차단 대기열이있을 수도 있습니다. 이후 훨씬 쉽게 일을 할 것이다 이러한 접근 방식은 관리하기 :

class Producer 
{ 
    //... 

    public void Produce() 
    { 
     for (int i = 1; i <= 4; i++) 
     { 
      Thread.Sleep(randomSleepTime.Next(1, 3000)); 
      blockingIntQueue.Enqueue(i); 
     } 
    } 
} 

귀하의 소비자가 지금과 같이 표시됩니다 :

class Consumer 
{ 
    //... 

    public void Consume() 
    { 
     int value = 0; 
     for (int i = 1; i <= 4; i++) 
     { 
      if(blockingIntQueue.TryDequeue(out value)) 
      { 
       sum += value; 
      } 
     } 
    } 
} 

을하지만, 당신이 어떤 종류의 경우합니다 (HoldInteger을 유지하려는 경우 요구 사항), 블로킹 큐를 버퍼가없는 대신 HoldIntegerUnsynchronized 클래스에 넣을 수 있습니다 (그렇게해야만합니다). 그러면 동일한 결과를 얻을 수 있습니다.

참고 : 더 이상 값이 누락 또는 스레드가 정확하게 적절한 시간에 일어나하지 않기 때문에 오래된 값을 읽기에 대해 걱정할 필요가 없습니다이 방법.

정수 홀더가 기본 "버퍼"를 안전하게 처리하더라도 여전히 원하는 모든 정수를 얻을 수 있다고 보장 할 수는 없습니다. 타이머가 충분히 정확하지 않기 때문에, 이런 종류의 물건은 전적으로 가능하고 처음에

사례 1

Producer wakes up and writes integer. 
Consumer wakes up and reads integer. 

Consumer wakes up and reads integer. 
Producer wakes up and writes integer. 

사례 2

Consumer wakes reads integer. 
Producer wakes up and writes integer. 

Producer wakes up and writes integer. 
Consumer wakes up and reads integer. 

:이 점을 고려 두 번째 경우에는 소비자가 가치를 놓치게되는 반면, 소비자는 부실 값을 읽게됩니다.

+0

대단히 감사합니다. 매우 유용합니다 :) –

+0

@Hossein, enjoy! :) – Kiril

1

당신은

class HoldIntegerUnsynchronized { 
    int buffer; 
    object syncLock = new object(); 
    bool goodToRead = false; 
    bool goodToWrite = true; 

    public int Buffer { 
     get { 
      lock (syncLock) { 
       while (!goodToWrite) 
        Monitor.Wait(syncLock); 
       buffer = value; 
       goodToWrite = false; 
       goodToRead = true; 
       Monitor.Pulse(syncLock); 
      } 
     } 
     set { 
      lock (syncLock) { 
       while (!goodToRead) 
        Monitor.Wait(syncLock); 
       int toReturn = buffer; 
       goodToWrite = true; 
       goodToRead = false; 
       Monitor.Pulse(syncLock); 
       return toReturn; 
      } 
     } 
    } 
} 

주 같은 것을 할 수있는이 코드는 테스트하지 않았습니다!

+0

예,이 방법을 사용했지만 런타임이 낭비 될 수 있다고 생각합니다. 제작자 스레드가 소비자가 그 값을 소비 할 수있는 것보다 더 빨리 값을 생성하는 경우 다음 값을 배치 할 다른 위치가 메모리에 없기 때문에 생성자 스레드는 소비자를 기다립니다. –