추상화클래스와 인터페이스의 용도, 차이점, 공통점

Posted by 나에요임마
2017. 9. 19. 11:27 Program/C#
abstract class와 interface는 비슷하지만 다르다.
공통점, 차이점, 용도에 대해 알아보자~



1. 공통점 

abstract class(추상 클래스)와 interface 는 선언만 있고 구현 내용이 없는 클래스이다.

그래서 자기 자신이 new를 해서 객체를 생성할 수 없으며,
추상클래스를 extends 받거나, interface를 implements 한 자식만이 객체를 생성할 수 있다.
상속받은 자식이 구현을 반드시 하도록 해야할 때 사용한다.

JAVA에서는 type이 지정되있기 때문에 선언된 type과 자식의 type이 같아야만 한다.



2. 차이점

추상클래스는 말그대로 클래스이고, interface는 구현하기 전에 메소드에 대해 명세된 것이랄까?
그래서 상속을 받음에도 불구하고 클래스에선 상속이라고 쓰지만 interface는 implemets(구현) 이라고 쓴다.

추상클래스의 정의는 abstract 메소드가 하나라도 존재하는 클래스를 일컫는다.
때문에 일부는 구현된 메소드도 있고, abstract라고 붙어있는 메소드는 구현이 안되어있다.

추상클래스를 상속받는 클래스는 반드시 추상메소드를 구현해야한다.
그래서 필수적으로 구현해야할 메소드가 있을 때 추상클래스를 쓰게된다.


인터페이스는 구현체 없이, 메소드에 대한 명세만 되어있다.
인터페이스를 상속받는 클래스에서는 반드시 인터페이스에 있는 메소드를 다 구현해야한다.

자바는 단일상속을 지원하기 때문에 추상클래스는 단일상속이지만, 
interface를 사용하게 되면, implements를 구현하는 부분에서 extends 또한 사용할 수 있다. 
즉, 다중상속이 가능해진다.


'이러이러한 메소드를 쓸 것이다.' 인터페이스에 선언을 해놓고, 가져다가 반드시 선언된 그대로 모두 구현하면 되는게 인터페이스이고,    

이러이러한 메소드가 있지만 가져다 쓰거나 오버라이드 하거나, abstract가 붙은 메소드는 반드시 구현하면 되는게 abstract class이다.



3. 용도

책을 아무리 읽고 인터넷을 찾아봐도 이해가 잘 안가는
추상클래스와 인터페이스의 용도!

그나마 조금 알게된 용도를 정리한다 ㅎㅎ



인터페이스를 설명하려면 다형성(Polymorphism)에 대한 개념이 등장한다.
다형성이라고 하면 어려울 것 같지만 아래같이 생각하면 쉬울 것이다.

interface : 동물

method : 먹는다, 걷는다, 잔다
구현체(implement) : 고양이, 원숭이, 병아리


동물들은 모두 먹고, 걷는다. 
하지만 동물들마다 먹고 걷는 방식은 다르다.

구현체에서는 동물 각각이 먹고 걷는 방식을 구현한다.
같은 '먹는다'라는 동사에서, 동물마다 여러가지 형태로 구현할 수 있기때문에 이름이 다형성.



그렇다면 인터페이스를 쓰면 얻는 이득이 무엇인가?

동물이 먹고, 걷고, 자는 것은 공통적인데, 그 것을 행하는 방법이 각자 다르다.
고양이는 걸을 때 네발로 걷고, 원숭이는 두발 또는 네발로, 병아리도 두발로..

그래서 동물이 먹고, 걷고, 잔다는 틀만 만들어놓고
고양이, 원숭이, 병아리는 그 틀안에 자신만의 방법으로 메소드를 구현하는 것이다.

반드시 구현체 동물들은 먹고 걷고 자는방법이 구현되어야 한다. 동물이라면..
그리고 고양이의 자는법이 달라져도 원숭이, 병아리에게는 아무 영향도 없다.



그럼 추상화 클래스는 언제 쓰는게 좋은가?


야생고양이가 새끼를 낳았다. 
새끼는 인간에 의해 집고양이가 되었다고하자.

어미고양이(부모클래스) - 야생고양이

  - 자는법 (메소드) 

  - 집에서 사는법 (추상화 메소드)


새끼고양이(자식클래스) - 집고양이

  - 자는법 (메소드)

  - 집에서 사는법 (메소드)


좀 억지이지만 ㅋㅋㅋ


어미고양이는 야생고양이므로, 
집에서 사는법은 모르지만, 새끼고양이는 집에서 사는법을 알려주기 위해 추상화 메소드로 만들었다.(구현X)

어미고양이는 자는법이 있었고, 자식에게 전수하였다.
그러나 자식은 집고양이라 어미고양이와 자는법이 달랐다.

그래서 자식고양이 나름대로 자는법을 새로 터득하였다.
그게 이미 구현되어있는 부모클래스의 내용을 Override를 하는 것이다.

새끼고양이는 집 생활을 하며, 어미고양이가 모르는, 집에 사는법을 더 많이 터득하였다.
(부모 클래스보다 더 많이 구현되는 경우가 대부분이다)



그니깐 총정리를 하면,
인터페이스는 다형성이라 생각하면되고,

상속은 부모 - 자식 관계.. 
부모가 갖고있는 기능을 유전 받으면서, 기능을 더 추가한다거나, 
부모의 유전된 기능을 약간 수정할 때 쓴다.


'Program > C#' 카테고리의 다른 글

Invoke() 이쁘게쓰기!  (0) 2017.10.11
시리얼통신  (1) 2017.10.02
DateTime & TimeSpan  (0) 2017.09.19
쓰레드 - Thread 클래스  (0) 2017.09.19
STAThread  (0) 2017.08.23

DateTime & TimeSpan

Posted by 나에요임마
2017. 9. 19. 10:58 Program/C#

우리나라 C#하는 사람들이 별로 없어서 그런걸까..
C#을 하는 사람이 없다기보다는.. C#으로 윈도우 프로그램을 만드는 사람이 별로 없는 것 같다.
델파이보다 오히려 더 적을지도...
아마추어들이 하려면 C++에 api mfc 핥아먹고 바로 C#으로 넘어오는 편이 더 나을 것 같은데...

--------

1.private void button1_Click(object sender, EventArgs e)
2.{
3.  TimeSpan asefnew TimeSpan(15,30,00);
4.  Console.WriteLine(asef);
5.  Console.WriteLine(DateTime.Now.Add(asef));//현재시간에 15시간을 더하기
6.  Console.WriteLine(DateTime.Now.TimeOfDay);//0시부터 현재시간까지를 TimeSpan값으로 반환
7.  Console.WriteLine(TimeSpan.Parse("15:30:00"));//TimeSpan값을 지정.. 문자열
8.}
DateTime과 TimeSpan 둘 다 시간을 표현한다.
다른점은...
DateTime은 몇월몇일몇시몇분을 달력이나 시계를 표현하고
TimeSpan은 1시간, 2시간,,,... 이런걸 표현한다고 할까..
시간과 시각?
전자시계 개념으로 설면하자면... 10분짜리 타이머를 맞춘다면... 
TimeSpan.. 알람을 맞추면..DateTime이렇게 보면 쉬울까...
DateTime - DateTime은 TimeSpan자료형이 된다.
(DateTime)2011년 2월 16일 21시 - (DateTime)2011년 2월 16일 15시 = (TimeSpan)6시간
위의 소스코드만으로도 설명은 충분할 것 같지만.... 추가하자면...
8시부터 뭔가를 실행시키고 싶다! 라고 한다면....
타이머 돌리고... System.Windows.Forms.Timer fajklefjl = new [tab] ();
if(DateTime.Now.TimeOfDay >TimeSpan.Parse("08:00:00"))

//***********************************************************************************************************

[펌] http://cafe.daum.net/vs.net/4sG8/20?docid=1HLyr|4sG8|20|20090326223655&q=c%23%20datetime

 

프로그램 시작시간
DateTime startTime = DateTime.Now;

// 1. 현재시간
DateTime now;
now = DateTime.Now;

Console.WriteLine(now); // 현재시간 전체
Console.WriteLine(now.Year); // 현재 년도
Console.WriteLine(now.Month); // 현재 달
Console.WriteLine(now.Day); // 현재 일
Console.WriteLine(now.DayOfWeek); // 현재 주
Console.WriteLine(now.DayOfYear); // 1년중 몇일째인지
Console.WriteLine(now.TimeOfDay); // 금일 자정부터 몇시간
Console.WriteLine(now.Hour); // 시간
Console.WriteLine(now.Minute); // 분
Console.WriteLine(now.Second); // 초
Console.WriteLine(now.Millisecond); // 1000분의 1초

Console.WriteLine(now.Ticks); // 1000분의 1초

// 2. 임의시간 설정
DateTime birthday;
birthday = DateTime.Parse("2009년8월9일"); // 시분초 미지정시 자정으로
birthday = DateTime.Parse("2009/08/09");

Console.WriteLine(birthday);

DateTime xmas;
xmasnew DateTime(20081225000);

Console.WriteLine(xmas);

// 3. 연산

// 3.1 오늘 + 100일
now = DateTime.Now;
DateTime result = now.AddDays(100); // 각 단위별 add메소드가 존재 MSDN참고

Console.WriteLine(result);

// 3.2 크리스마스까지 남은 날
TimeSpan result2 = xmas - now;
Console.WriteLine(result2);
Console.WriteLine(result2.Days); // NNN일 (내림표현)
Console.WriteLine(result2.TotalDays); // NNN.NNNNNNN일 (더정확)

// 3.3 오늘 - 100일
Console.WriteLine(now - TimeSpan.FromDays(100));
Console.WriteLine(now.AddDays(-100));

// 4. 날짜시간 출력형식 지정
Console.WriteLine(now.ToLocalTime()); // 2008-08-08 오전 10:31:25

Console.WriteLine(now.ToLongDateString()); // 2008년 8월 8일 금요일
Console.WriteLine(now.ToShortDateString()); // 2008-08-08

Console.WriteLine(now.ToLongTimeString()); // 오전 10:31:25
Console.WriteLine(now.ToShortTimeString());   // 오전 10:31

// 프로그램 종료시간
DateTime endTime = DateTime.Now;

Console.WriteLine("프로그램 수행시간 : {0}/ms", (double)(endTime - startTime).Ticks / 1000000.0F);

 

 

[ DateTimeFormatInfo ]

 

Format Character
Associated Property/ Description
dShortDatePattern
DLongDatePattern
fFull date and time (long date and short time)
FFullDateTimePattern (long date and long time)
gGeneral (short date and short time)
GGeneral (short date and long time)
m, MMonthDayPattern
r, RRFC1123Pattern
sSortableDateTimePattern (based on ISO 8601) using local time
tShortTimePattern
TLongTimePattern
uUniversalSortableDateTimePattern using the format for universal time display
UFull date and time (long date and long time) using universal time
y, YYearMonthPattern
  
dThe day of the month. Single-digit days will not have a leading zero.
ddThe day of the month. Single-digit days will have a leading zero.
dddThe abbreviated name of the day of the week, as defined in AbbreviatedDayNames.
ddddThe full name of the day of the week, as defined in DayNames.
MThe numeric month. Single-digit months will not have a leading zero.
MMThe numeric month. Single-digit months will have a leading zero.
MMMThe abbreviated name of the month, as defined in AbbreviatedMonthNames.
MMMMThe full name of the month, as defined in MonthNames.
yThe year without the century. If the year without the century is less than 10, the year is displayed with no leading zero.
yyThe year without the century. If the year without the century is less than 10, the year is displayed with a leading zero.
yyyyThe year in four digits, including the century.
ggThe period or era. This pattern is ignored if the date to be formatted does not have an associated period or era string.
hThe hour in a 12-hour clock. Single-digit hours will not have a leading zero.
hhThe hour in a 12-hour clock. Single-digit hours will have a leading zero.
HThe hour in a 24-hour clock. Single-digit hours will not have a leading zero.
HHThe hour in a 24-hour clock. Single-digit hours will have a leading zero.
mThe minute. Single-digit minutes will not have a leading zero.
mmThe minute. Single-digit minutes will have a leading zero.
sThe second. Single-digit seconds will not have a leading zero.
ssThe second. Single-digit seconds will have a leading zero.
fThe fraction of a second in single-digit precision. The remaining digits are truncated.
ffThe fraction of a second in double-digit precision. The remaining digits are truncated.
fffThe fraction of a second in three-digit precision. The remaining digits are truncated.
ffffThe fraction of a second in four-digit precision. The remaining digits are truncated.
fffffThe fraction of a second in five-digit precision. The remaining digits are truncated.
ffffffThe fraction of a second in six-digit precision. The remaining digits are truncated.
fffffffThe fraction of a second in seven-digit precision. The remaining digits are truncated.
tThe first character in the AM/PM designator defined in AMDesignator or PMDesignator, if any.
ttThe AM/PM designator defined in AMDesignator or PMDesignator, if any.
zThe time zone offset ("+" or "-" followed by the hour only). Single-digit hours will not have a leading zero. For example, Pacific Standard Time is "-8".
zzThe time zone offset ("+" or "-" followed by the hour only). Single-digit hours will have a leading zero. For example, Pacific Standard Time is "-08".
zzzThe full time zone offset ("+" or "-" followed by the hour and minutes). Single-digit hours and minutes will have leading zeros. For example, Pacific Standard Time is "-08:00".
:The default time separator defined in TimeSeparator.
/The default date separator defined in DateSeparator.
cWhere c is a format pattern if used alone. The "%" character can be omitted if the format pattern is combined with literal characters or other format patterns.
cWhere c is any character. Displays the character literally. To display the backslash character, use "\\".

 

Only format patterns listed in the second table above can be used to create custom patterns; standard format characters listed in the first table cannot be used to create custom patterns. Custom patterns are at least two characters long; for example,

  • DateTime.Now.ToString( "d") returns the DateTime value; "d" is the standard short date pattern.
  • DateTime.Now.ToString( "%d") returns the day of the month; "%d" is a custom pattern.
  • DateTime.Now.ToString( "d ") returns the day of the month followed by a white-space character; "d " is a custom pattern.


'Program > C#' 카테고리의 다른 글

시리얼통신  (1) 2017.10.02
추상화클래스와 인터페이스의 용도, 차이점, 공통점  (0) 2017.09.19
쓰레드 - Thread 클래스  (0) 2017.09.19
STAThread  (0) 2017.08.23
프로세스 스케줄링(Process Scheduling)  (0) 2017.07.05

쓰레드 - Thread 클래스

Posted by 나에요임마
2017. 9. 19. 10:49 Program/C#
쓰레드란 CPU를 이용하는 가장 작은 단위인데 싱글 쓰레드를 사용하면 CPU의 사용 권한을 하나의 쓰레드가 독차지 하게 된다. 지하철 개찰구의 예를들면 개찰구가 하나라면 평상시에는 큰 무리가 아니지만 출퇴근 시간에는 무리가 따를 수 있다. 결국 개찰구를 늘여야 한다는 것이다. 프로그래밍에서 볼 때 개찰구를 늘이는 것이 멀티 쓰레드를 이용하는 것이다. 멀티 쓰레드가 제대로 동작하기 위해서는 CPU가 여러 개 있어야 한다. 보통은 단일 CPU를 사용 할 것이다. CPU는 한번에 하나의 쓰레드를 사용하므로 멀티 쓰레드 프로그램이 실행되는 경우에는 CPU의 사용 시간을 나누어서 각각의 쓰레드에게 나누어 주는 것이다. 결국 개찰구는 늘였지만 표를 파는 곳은 한 군데 인것이다.
 
C#에서의 멀티 쓰레드
 
C#에서 멀티 쓰레드를 사용하는 방법은 기 정의된 쓰레드 클래스를 사용하면 된다. 결국 배워야 하는 것은 C#에서 멀티 쓰레드를 위한 클래스가 어떤 것이 있고 그 사용법은 어떻게 되는가 이다. 쓰레드를 위한 개체들은 System.Threading 네임스페이스 안에 정의 되어 있다.
 
[첫번째 예제]
using System;
using System.Threading;
 
public class ThreadTest
{
        public void FirstWork()
        {
               for(int i=0; i < 100; i++)
               {
                       Thread.Sleep(1000);  //밀리세컨드 단위
                       Console.Write("F{0} " ,i);
                }
        }
 
        public void SecondWork()
        {
               for(int i=0; i < 100; i++)
               {
                       Thread.Sleep(1000);
                       Console.Write("S{0} " ,i);
               }
        }
 
        [MTAThread]
        public static void Main()
        {
               ThreadTest t = new ThreadTest();
 
               //Thread는 생성자에 ThreadStart형 Delegate를 인자로 받는다.
               Thread first = new Thread(new ThreadStart(t.FirstWork));
               Thread second = new Thread(new ThreadStart(t.SecondWork));
 
               first.Start();
               second.Start();
        }
}
 
[예제1-1]
using System;
using System.Threading;
class ThreadTest
{
        static void Thmethod()
        {
               int id = AppDomain.GetCurrentThreadId();
               Console.WriteLine("Thread[{0}] Thmethod Method Running",id);
        }
        static void Main()
        {
               int id = AppDomain.GetCurrentThreadId();
               Console.WriteLine("Main Thread[{0}]",id);
               for(int i=0;i<10;i++)
               {
                       Thread th = new Thread(new ThreadStart(Thmethod));
                       th.Start();
               }
        }
}
 
 
Thread.Sleep 안에는 해당 Thread가 얼마만큼 쉴 건지에 대한 시간을 밀리 세컨드단위로 지정 한다. 만약 시간을 0으로 설정하면 현재 자신에게 주어진 시간을 다른 쓰레드에게 쓰게 하겠다는 의미이다. 지금 당장은 CPU를 사용 하지 않아도 될 때 다른 쓰레드에게  CPU를 사용 할 기회를 줌으로써 CPU를 효율적으로 이용 할 수 있다. 쓰레드를 쉐게 하는 방법은 Thread.Suspend 를 이용 할 수도 있다. Sleep과의 차이는 Sleep인 경우엔 지정한 시간 만큼 쉰다는 의미지만 Suspend인 경우엔 Resume 메소드를 호출 할 때 까지 쉬게 된다는 것이다.또 다른 차이점은 Sleep 메소드는 자기 자신의 쓰레드만 쉬게 할 수 있다. 반면에 Suspend 는 자기 뿐 아니라 다른 쓰레드도 쉬게 할 수 있다.잠을 자고 있는 Thread가 스스로 깰 수는 없다. 그래서 Suspend로 쉬고 있는 쓰레드는 다른 쓰레드가 Resume을 이용하여 깨울 때 까지 쉬고 있는 것이다. 주의 할 점은 Sleep인 경우는 쓰레드가 즉시 중단 되지만 Suspend로 쉬게 할려면 즉시 중단 되지 않는다.
 
[예제2]
using System;
using System.Threading;
 
public class ThreadTest2
{
        public bool sleep = false;
        public void FirstWork()
        {
               for(int i=0; i < 10; i++)
               {
                       Console.WriteLine("F{0}", i);
                       if (i == 5)
                       {
                              sleep = true;
                              Console.WriteLine("");
                              Console.WriteLine("first 쉼...");
                              Thread.CurrentThread.Suspend();
                       }
               }
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest2 t = new ThreadTest2();
               Thread first = new Thread(new ThreadStart(t.FirstWork));
 
               first.Start();
 
               while(t.sleep == false) {}
 
               Console.WriteLine("");
               Console.WriteLine("first를 깨웁니다...");
               first.Resume();
        }
}
Suspend 메소드로 쓰레드를 잠시 중지하면 Resume 메소드로 다시 동작하게 할 수 있지만 Thread.Abort로 일단 쓰레드를 종료 시키면 다시 되살릴 수 없다.쓰레드가 확실히 종료 되었는지를 살펴보기 위해서는 Thead.Join 메소드를 사용 할 수 있는데 Thread.Join 메소드는 동기적으로 동작하므로 쓰레드가 종료 할 때까지 기다리게 된다. 만일 어떤 이유에서든지 쓰레드가 종료 되지 않는 다면 무한정 기다릴 수 밖에  없다. Thread.Join 메소드 안에 1/1000초 단위로 파라미터를 전달 할 수 있는데이것은 얼마 만큼 Join으로 붙은 쓰레드가 종료 될 때까지 기다릴 수 있는 가에 대한 값이다. 만일 주어진 시간안에 종료되면 true를 반환하고 기다리기를 중지 한다면 false 값을 반환 한다.
 
쓰레드가 여러 개 있다면 한 쓰레드가 동작하고 나서 어떤 쓰레드가 동작 할까? 아마도 높은 우선 순위를 가지고 있는 쓰레드가 수행 될 것이다. 각각의 쓰레드는 CPU 사용 권한에 대한 우선 순위가 있는데 우선 순위가 높을수록 CPU사용 권한을 먼저 할당 받는다.
 
아래의 예제를 보도록 하자.
 
using System;
using System.Threading;
 
public class ThreadTest3
{
        public bool sleep = false;
        public void FirstWork()
        {
               for(int i=0; i < 10; i++)
               {
                       for(int j=0; j < 10; j++)
                       {
                              Thread.Sleep(100);
                              Console.Write(",");
                       }
 
                       Console.WriteLine("F{0}", i);
               }
        }
 
        public void SecondWork()
        {
               for(int i=0; i < 10; i++)
               {
                       for(int j=0; j < 10; j++)
                       {
                              Thread.Sleep(100);
                              Console.Write(",");
                       }
 
                       Console.WriteLine("S{0}", i);
               }
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest3 t = new ThreadTest3();
               Thread first = new Thread(new ThreadStart(t.FirstWork));
               Thread second = new Thread(new ThreadStart(t.SecondWork));
 
               first.Start();
               second.Start();
        }
}
 
위의 예제를 실행해 보면 각각의 쓰레드가 할당 받은 시간이 비슷함을 알 수 있다. 두개의 쓰레드가 우선 순위가 비슷 하니까 아래의 그림과 같은 결과가 나오는 것이다.

 
아래의 예는 Join을 이용한 예제이다.
 first.Join() 부분을 주석으로 막은 후 다시 실행 해 보라.
 
using System;
using System.Threading;
 
public class ThreadTest2
{
        public int[] iArray = new int[100];
        public void CollectData()
        {
               for(int i=0; i <= 20; i++)
               {
                       iArray[i] = i+1;
                       Console.Write(",");
                       Thread.Sleep(500);
               }
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest2 t = new ThreadTest2();
               Thread first = new Thread(new ThreadStart(t.CollectData));
              
               first.Start();
               first.Join();
 
               int sum=0;
               for(int i=0; i<t.iArray.Length; i++)
               {
                       sum += t.iArray[i];
               }
              
               Console.WriteLine();
               Console.WriteLine("sum = {0}", sum);
        }
}
 
 
한 쓰레드에 대해 우선순위를 높여 주면 CPU 사용 권한을 우선적으로 갖는 것이다.  Thread의 우선 순위와 관련된 프로퍼티가 있는데 열거형 값인 Highest, AboveNormal, Normal, BelowNormal, Lowest중 한 값이다. 아래의 예제를 살펴 보자.
 
 
using System;
using System.Threading;
 
public class ThreadTest3
{
        public bool sleep = false;
        public void FirstWork()
        {
               for(int i=0; i < 10; i++)
               {
                       for(int j=0; j < 10; j++)
                       {
                              Thread.Sleep(100);
                              Console.Write(",");
                       }
 
                       Console.WriteLine("F{0}", i);
               }
        }
 
        public void SecondWork()
        {
               for(int i=0; i < 10; i++)
               {
                       for(int j=0; j < 10; j++)
                       {
                              Thread.Sleep(100);
                              Console.Write(",");
                       }
 
                       Console.WriteLine("S{0}", i);
               }
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest3 t = new ThreadTest3();
               Thread first = new Thread(new ThreadStart(t.FirstWork));
               Thread second = new Thread(new ThreadStart(t.SecondWork));
 
               first.Priority = ThreadPriority.Lowest;
 
               first.Start();
               second.Start();
        }
}
 

 
 
멀티쓰레드 환경인 경우 여러 곳에서 같은 객체의 메소드를 호출 하는 경우에 예기치 않은 결과가 나타날 수 있다. 어떤 메소드의 사용을  한 쓰레드가 끝난 후 다른 쓰레드가 접근하게 하려면 lock 문을 사용 한다. 다음의 예제를 보도록 하자.
 
 
using System;
using System.Threading;
 
public class ThreadTest3
{
        public string lockString = "Hello";
        public void Print(string rank)
        {
               //lock을 걸어준 구문은 처음 쓰레드가 끝날때 까지 다른 쓰레드가 접근 금지
               lock (this)
               {
                       for(int i=0; i < 10; i++)
                       {
                              for(int j=0; j < 10; j++)
                              {
                                      Thread.Sleep(100);
                                      Console.Write(",");
                              }
 
                              Console.WriteLine("{0}{1} ", rank, lockString);
                       }
               }
        }
 
        public void FirstWork()
        {
               Print("F");
        }
 
        public void SecondWork()
        {
               Print("S");
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest3 t = new ThreadTest3();
               Thread first = new Thread(new ThreadStart(t.FirstWork));
               Thread second = new Thread(new ThreadStart(t.SecondWork));
 
               first.Start();
               second.Start();
        }
}
 
 
lock 문 이외에 System.Monitor라는 클래스가 있는데 이 Monitor 클래스에는 Enter,Exit 메소드가 있는데 Enter 메소드는 잠금 상황으로, Exit 메소드는 잠금을 해제하는 역할을 한다. 앞에서 작성한 예제를 System.Monitor를 이용하는 예문으로 바꿔 보자…
 
using System;
using System.Threading;
 
public class ThreadTest3
{
        public string lockString = "Hello";
        public void Print(string rank)
        {
               //lock을 걸어준 구문은 처음 쓰레드가 끝날때 까지 다른 쓰레드가 접근 금지
               Monitor.Enter(this);
               for(int i=0; i < 10; i++)
               {
                       for(int j=0; j < 10; j++)
                       {
                              Thread.Sleep(100);
                              Console.Write(",");
                       }
 
                       Console.WriteLine("{0}{1} ", rank, lockString);
               }
               Monitor.Exit(this);
        }
 
        public void FirstWork()
        {
               Print("F");
        }
 
        public void SecondWork()
        {
               Print("S");
        }
}
 
class TestMain
{
        [MTAThread]
        public static void Main()
        {
               ThreadTest3 t = new ThreadTest3();
               Thread first = new Thread(new ThreadStart(t.FirstWork));
               Thread second = new Thread(new ThreadStart(t.SecondWork));
 
               first.Start();
               second.Start();
        }
}


'Program > C#' 카테고리의 다른 글

추상화클래스와 인터페이스의 용도, 차이점, 공통점  (0) 2017.09.19
DateTime & TimeSpan  (0) 2017.09.19
STAThread  (0) 2017.08.23
프로세스 스케줄링(Process Scheduling)  (0) 2017.07.05
함수와 return  (0) 2017.06.29