2014-11-14 3 views
1

다음은 프로그램에서 수행해야 할 작업에 대한 설명입니다. 프로그램은 파일과 5 개의 스레드를 작성하여 해당 파일에 기록해야합니다. ...C에서 스레드 5 개로 시간 분할 #

첫 번째 스레드는 1에서 5까지를 해당 파일에 기록해야합니다. 번째 스레드가 제 스레드가 제 스레드가 제 스레드 또한 25

1에서 작성해야 1 (20)에서 작성해야 1 (15)에서 작성해야 1 10 내지 작성해야 각 스레드가 2 개의 숫자를 인쇄하고 중지하도록 알고리즘을 구현해야합니다. 다음 스레드는 두 개의 숫자를 인쇄하고 중지해야합니다. 모든 스레드가 숫자 인쇄를 마칠 때까지 계속됩니다. 여기 ... 여기

using System; 
using System.IO; 
using System.Threading; 
using System.Collections; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    public static class OSAssignment 
    { 
     // First Thread Tasks... 
     static void FirstThreadTasks(StreamWriter WritingBuffer) 
     { 
      for (int i = 1; i <= 5; i++) 
      { 
       if (i % 2 == 0) 
       { 
        Console.WriteLine("[Thread1] " + i); 
        Thread.Sleep(i); 
       } 

       else 
       { 
        Console.WriteLine("[Thread1] " + i); 
       } 
      } 
     } 

     // Second Thread Tasks... 
     static void SecondThreadTasks(StreamWriter WritingBuffer) 
     { 
      for (int i = 1; i <= 10; i++) 
      { 
       if (i % 2 == 0) 
       { 
        if (i == 10) 
         Console.WriteLine("[Thread2] " + i); 

        else 
        { 
         Console.WriteLine("[Thread2] " + i); 
         Thread.Sleep(i); 
        } 
       } 

       else 
       { 
        Console.WriteLine("[Thread2] " + i); 
       } 
      } 
     } 

     // Third Thread Tasks.. 
     static void ThirdThreadTasks(StreamWriter WritingBuffer) 
     { 
      for (int i = 1; i <= 15; i++) 
      { 
       if (i % 2 == 0) 
       { 
        Console.WriteLine("[Thread3] " + i); 
        Thread.Sleep(i); 
       } 

       else 
       { 
        Console.WriteLine("[Thread3] " + i); 
       } 
      } 
     } 

     // Fourth Thread Tasks... 
     static void FourthThreadTasks(StreamWriter WritingBuffer) 
     { 
      for (int i = 1; i <= 20; i++) 
      { 
       if (i % 2 == 0) 
       { 
        if (i == 20) 
         Console.WriteLine("[Thread4] " + i); 
        else 
        { 
         Console.WriteLine("[Thread4] " + i); 
         Thread.Sleep(i); 
        } 
       } 

       else 
       { 
        Console.WriteLine("[Thread4] " + i); 
       } 

      } 
     } 

     // Fifth Thread Tasks... 
     static void FifthThreadTasks(StreamWriter WritingBuffer) 
     { 
      for (int i = 1; i <= 25; i++) 
      { 
       if (i % 2 == 0) 
       { 
        Console.WriteLine("[Thread5] " + i); 
        Thread.Sleep(i); 
       } 

       else 
       { 
        Console.WriteLine("[Thread5] " + i); 
       } 

      } 
     } 

     // Main Function... 
     static void Main(string[] args) 
     { 
      FileStream File = new FileStream("output.txt", FileMode.Create, FileAccess.Write, FileShare.Write); 
      StreamWriter Writer = new StreamWriter(File); 
      Thread T1 = new Thread(() => FirstThreadTasks(Writer)); 
      Thread T2 = new Thread(() => SecondThreadTasks(Writer)); 
      Thread T3 = new Thread(() => ThirdThreadTasks(Writer)); 
      Thread T4 = new Thread(() => FourthThreadTasks(Writer)); 
      Thread T5 = new Thread(() => FifthThreadTasks(Writer)); 
      Console.WriteLine("Initiating Jobs..."); 
      T1.Start(); 
      T2.Start(); 
      T3.Start(); 
      T4.Start(); 
      T5.Start(); 
      Writer.Flush(); 
      Writer.Close(); 
      File.Close(); 
     } 
    } 
} 

내가 직면하고있어 문제의 ... 내가 지금까지 개발 한 코드의

    나는 5 개 스레드가로 작성하는 방법을 알아낼 수 없습니다
  1. FileShare.Write을 만들 때조차도 같은 파일을 만듭니다. 그래서 나는 당분간 콘솔에 글을 쓰고 알고리즘을 개발하고 콘솔에서 어떻게 동작하는지 보았습니다.

  2. 프로그램을 실행할 때마다 출력이 이전과 약간 다릅니다. 스레드가 특정 반복에서 숫자 중 하나만 인쇄하고 다른 스레드가 현재 반복을 마친 후에 두 번째 숫자를 계속 출력합니다.

  3. 나는 어떻게 든 오프 트랙일지도 모르는 질문이있다. 주 방법에서 Console.WriteLine("Initiating Jobs...");을 제거하면 알고리즘은 Point 2에서 언급 한 것처럼 작동하지 않습니다. 이유를 알 수 없습니다.

답변

2

James의 답변도 참조하십시오. 그는 제 통지를 피한 치명적인 버그를 지적합니다. 작가 스레드가 끝나기 전에 파일을 닫는 것입니다. 이 "문제"는 이미 세 가지 질문이 하나로 통합되어 있기 때문에 새로운 문제를 게시하여 문제 해결 방법을 묻는 것이 좋습니다.

  1. FileShare.Write는 파일을 쓰기 위해 다른 시도를 허용하도록 운영 체제에 알립니다. 일반적으로 이것은 동일한 파일에 여러 개의 프로세스를 작성하는 시스템에 사용됩니다. 귀하의 경우 단일 프로세스가 있으며 파일을 한 번만 열어서이 플래그는 실제로 아무런 차이가 없습니다. 그것은 직업에 대한 잘못된 도구입니다.

여러 스레드간에 쓰기를 조정하려면 잠금을 사용해야합니다. 클래스에 새 정적 필드를 추가 : 콘솔을 사용하는 동안이 차이를하지 않습니다 줘야

lock(synchronizer) 
{ 
    Console.WriteLine("[Thread1] " + i);  
} 

:

private static object synchronizer = new object(); 

그런 다음 해당 객체에 대한 잠금을 사용하여 파일의 각 쓰기 작업을 마무리 ,하지만 나는 파일에 쓰는 것과 관련된 문제를 해결할 것이라고 생각합니다.

말하자면, 파일 쓰기에서 콘솔 쓰기로 전환하면 파일 문제를 피하는 것이 영리한 아이디어 였으므로 그 점을 명심하십시오. Howver는이 아이디어를 훨씬 더 잘 구현하기 위해 모든 쓰기 호출을 하나의 함수 (예 : "WriteOutput (string)"을 사용하면 해당 기능에서 한 줄만 변경하여 파일에서 콘솔로 모든 것을 전환 할 수 있습니다.

그러면 잠금 기능을 해당 기능에도 넣을 수 있습니다.

  1. 스레드 물건은 결정적이지 않습니다. 각 스레드가 실행되지만 스레드가 인터럽트 될 스레드, 인터럽트 할 인터럽트 등을 보장하지는 않습니다. 매번 주사위를 굴립니다. 당신은 단지 익숙해 져야 만합니다. 그렇지 않으면 당신의 응용 프로그램에 정말로 중요한 일이 생기면 특정 순서대로 일이 진행되도록해야합니다.

  2. 나는 이것에 대해 몰라. 그건 중요하지 않은 것 같아.

+0

Sir, 한 스레드가 파일에 쓰는 동안 다른 스레드가 비활성 상태인지 확인하는 방법이 있습니까? 따라서 발생하는 중단을 방지 할 수 있습니까? – user3490561

+0

그것이 바로 잠금이하는 것입니다. 스레드가 잠금을 취한 후 잠금을 시도하는 다음 스레드는 잠금이 해제 될 때까지 대기합니다 (잠금을 가진 스레드가 "{{lock}}"문을 종료 할 때 발생 함). 그래서 모든 글이 "lock (synchronizer)"안에 있다면 어느 순간에도 하나의 쓰레드 만 쓸 수 있습니다. – NSFW

+0

또한, 필자는 내 대답에 서문을 추가했습니다. 다시 읽어보십시오. :-) – NSFW

4
  1. 귀하의 주요 기능은 마무리 스레드가 그것을 쓰기 시작하기 전에 당신이 스레드가 종료 때까지 기다릴 Thread.join를 사용할 수 있도록 파일을 닫는. 또한 IDisposable 개체에 대해 using 문을 사용하는 것이 좋습니다.

  2. 스레드간에 공유하려는 제한된 리소스가있는 경우 잠금 메커니즘이 필요합니다. 스레드 스케줄링은 결정적이지 않습니다. 5 개의 스레드를 시작했으며 그 시점에서 어느 것이 먼저 실행되는지는 보장되지 않습니다. lock은 스레드가 리소스가 해제 될 때까지 대기하도록합니다. 순서가 여전히 결정되지 않아 주문을 강제하기 위해 추가 논리/잠금을 추가하지 않으면 T3가 T2 이전에 실행될 수 있습니다.

  3. 자유로운 실행 스레드는 타이밍 문제와 관련하여 특히 버그를 찾기가 쉽지 않습니다.

여분의 참고로 스레드 동기화 방법으로 Sleep을 사용하지 마십시오.

효과적으로 다른 모든 스레드를 차단해야 한 번에 작성하는 하나 개의 스레드를 얻으려면 같은 lock, Mutex, Monitor, AutoResetEvent 등 내가이 상황에 대한 AutoResetEvent를 사용하는 거라고 수행하기위한 몇 가지 방법이있다. 그런 다음 문제는 각 스레드가 올바른 이벤트를 기다릴 수 있도록 대기중인 스레드를 알아야한다는 것입니다.

0

확인, 차라리 늦게 오는거야,하고 있지만, 여러 스레드에서보기, I/O의 이론적 관점에서 특정 엔드 포인트에 필연적으로 내포이다.

위 예제에서, 출력을 메모리 구조로 대기열에 넣고, 각 스레드가 그렇게하기 전에 배타적 잠금을 취한 다음 장치에 출력 할 별도의 스레드를 갖는 것이 훨씬 빠르고 안전합니다.