Skip to content

Instantly share code, notes, and snippets.

@Gumball12
Last active June 15, 2019 05:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Gumball12/a1f2947c79a56c146638dcbb979e850f to your computer and use it in GitHub Desktop.
Save Gumball12/a1f2947c79a56c146638dcbb979e850f to your computer and use it in GitHub Desktop.
c# assignment 9

CS assignment - week 9

9주차 c# 과제 레포트입니다.

모든 코드는 gist(https://git.io/fjGar)에 업로드하였습니다.

Problem 1

쓰레드를 사용하여 실행 간격이 각기 다르게(1초, 2초, 3초) 동작하는 프로그램을 작성하는 문제입니다.

먼저 출력은 다음과 같습니다.

problem 1

이 문제는 Thread가 어떻게 동작하는지만 잘 파악하고 있으면 큰 어려움 없이 해결이 가능한 문제입니다.

[Thread에 대한 설명]

이러한 것을 구현한 코드는 다음과 같습니다.

using System;
using System.Threading;

namespace Problem_1
{
    class Program
    {
        // global time
        private static int s = 0;

        // get ThreadStart instance
        private static ThreadStart getThreadStart (int i) {
            return new ThreadStart(() =>
            {
                // sub thread loop
                while (true)
                {
                    if (i == 1)
                    {
                        Console.WriteLine($"{i}번 쓰레드 {s}");
                    } else
                    {
                        Console.WriteLine($"{i}번 쓰레드");
                    }

                    Thread.Sleep(i * 1000);
                }
            });
        }

        static void Main(string[] args)
        {
            Console.WriteLine("쓰레드\t현재 초\n--------------------");

            // create Thread instance with ThereadStart object
            Thread t1 = new Thread(getThreadStart(1));
            Thread t2 = new Thread(getThreadStart(2));
            Thread t3 = new Thread(getThreadStart(3));

            // create branch
            t1.Start();
            t2.Start();
            t3.Start();

            Thread.Sleep(10); // init thread

            // main thread loop
            while (true)
            {
                s++;
                Console.WriteLine($"--------------------");
                Thread.Sleep(1000);
            }
        }
    }
}

Problem 2

문제 2번은 계좌와 사용자를 구현하는 문제입니다. 출력은 다음과 같습니다.

problem 2

이 문제는 cs의 lock statement를 사용할 줄 아는지 물어보는 문제라 할 수 있습니다. cs에서의 thread-safe를 위한 synchronous 구문은 lock 문을 사용하는데, 이를 위해서는 다음과 같이 lock object 를 정의해주어야 합니다.

[lock object, lock statement 에 대한 설명]

class Account
{
    private readonly object lockObject = new object(); // lock object

    public void func ()
    {
        lock (lockObject) // thread-safe statement
        {
            /* ... */
        }
    }
}

이러한 것을 구현한 코드는 다음과 같습니다.

using System;

namespace Problem_2
{
    class Program
    {
        static void Main(string[] args)
        {
            // create Account and Teller instances
            Account a = new Account(10000);
            Teller user = new Teller("홍길동", a, 0);

            // init variables
            byte command = 0;
            decimal insert;

            // print user balance
            user.printBalance();

            // loop
            while (command != 4)
            {
                Console.WriteLine("\n1. 입금\n2. 출금\n3. 조회\n4. 종료");

                command = Convert.ToByte(Console.ReadLine());

                switch (command)
                {
                    case 1:
                        Console.Write("입금 금액: ");
                        insert = getInsert();
                        user.credit(insert);
                        break;
                    case 2:
                        Console.Write("출금 금액: ");
                        insert = getInsert();
                        user.debit(insert);
                        break;
                    case 3:
                        user.printBalance();
                        break;
                    case 4:
                        Console.WriteLine("이용해주셔서 감사합니다.");
                        break;
                    default:
                        Console.WriteLine("잘못 입력하셨습니다.");
                        break;
                }
            }
        }

        // return uesr input
        static decimal getInsert ()
        {
            return Convert.ToDecimal(Console.ReadLine());
        }
    }

    // Account class
    class Account
    {
        // field
        private decimal balance = 0;
        private readonly object lockObject = new object(); // lock object

        // constructor
        public Account (decimal balance)
        {
            this.balance = balance;
        }

        // property
        public decimal Balance
        {
            get { return balance; }
        }

        // methods
        public void credit (decimal v) {
            lock (lockObject) // synchronous thread
            {
                balance += v;
            }
        }

        public bool debit (decimal v)
        {
            lock (lockObject) // synchronous thread
            {
                if (balance < v)
                {
                    return false;
                }

                balance -= v;
                return true;
            }
        }
    }

    // Teller class
    class Teller
    {
        // field
        private string name;
        private Account account;

        // constructor
        public Teller (string name, Account account, decimal v)
        {
            this.name = name;
            this.account = account;

            account.credit(v);
        }

        // methods
        public void printBalance ()
        {
            Console.WriteLine($"{name}님의 현재 잔액은 {account.Balance}원입니다.");
        }

        public void credit (decimal v)
        {
            account.credit(v);
            Console.WriteLine($"{name}님의 입금 후 잔액은 {account.Balance} 입니다.");
        }

        public void debit (decimal v)
        {
            if (account.debit(v) == true)
            {
                Console.WriteLine($"{name}님의 출금 후 잔액은 {account.Balance} 입니다.");
            } else
            {
                Console.WriteLine("잔액이 부족합니다.");
            }
        }
    }
}
using System;
using System.Threading;
namespace Problem_1
{
class Program
{
// global time
private static int s = 0;
// get ThreadStart instance
private static ThreadStart getThreadStart (int i) {
return new ThreadStart(() =>
{
// sub thread loop
while (true)
{
if (i == 1)
{
Console.WriteLine($"{i}번 쓰레드 {s}");
} else
{
Console.WriteLine($"{i}번 쓰레드");
}
Thread.Sleep(i * 1000);
}
});
}
static void Main(string[] args)
{
Console.WriteLine("쓰레드\t현재 초\n--------------------");
// create Thread instance with ThereadStart object
Thread t1 = new Thread(getThreadStart(1));
Thread t2 = new Thread(getThreadStart(2));
Thread t3 = new Thread(getThreadStart(3));
// create branch
t1.Start();
t2.Start();
t3.Start();
Thread.Sleep(10); // init thread
// main thread loop
while (true)
{
s++;
Console.WriteLine($"--------------------");
Thread.Sleep(1000);
}
}
}
}
using System;
namespace Problem_2
{
class Program
{
static void Main(string[] args)
{
// create Account and Teller instances
Account a = new Account(10000);
Teller user = new Teller("홍길동", a, 0);
// init variables
byte command = 0;
decimal insert;
// print user balance
user.printBalance();
// loop
while (command != 4)
{
Console.WriteLine("\n1. 입금\n2. 출금\n3. 조회\n4. 종료");
command = Convert.ToByte(Console.ReadLine());
switch (command)
{
case 1:
Console.Write("입금 금액: ");
insert = getInsert();
user.credit(insert);
break;
case 2:
Console.Write("출금 금액: ");
insert = getInsert();
user.debit(insert);
break;
case 3:
user.printBalance();
break;
case 4:
Console.WriteLine("이용해주셔서 감사합니다.");
break;
default:
Console.WriteLine("잘못 입력하셨습니다.");
break;
}
}
}
// return uesr input
static decimal getInsert ()
{
return Convert.ToDecimal(Console.ReadLine());
}
}
// Account class
class Account
{
// field
private decimal balance = 0;
private object _lock = new object(); // lock object
// constructor
public Account (decimal balance)
{
this.balance = balance;
}
// property
public decimal Balance
{
get { return balance; }
}
// methods
public void credit (decimal v) {
lock (_lock) // synchronous thread
{
balance += v;
}
}
public bool debit (decimal v)
{
lock (_lock) // synchronous thread
{
if (balance < v)
{
return false;
}
balance -= v;
return true;
}
}
}
// Teller class
class Teller
{
// field
private string name;
private Account account;
// constructor
public Teller (string name, Account account, decimal v)
{
this.name = name;
this.account = account;
account.credit(v);
}
// methods
public void printBalance ()
{
Console.WriteLine($"{name}님의 현재 잔액은 {account.Balance}원입니다.");
}
public void credit (decimal v)
{
account.credit(v);
Console.WriteLine($"{name}님의 입금 후 잔액은 {account.Balance} 입니다.");
}
public void debit (decimal v)
{
if (account.debit(v) == true)
{
Console.WriteLine($"{name}님의 출금 후 잔액은 {account.Balance} 입니다.");
} else
{
Console.WriteLine("잔액이 부족합니다.");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment