๐Ÿ™‡โ€โ™€๏ธSpinLock

ํ™”์žฅ์‹ค์— ์‚ฌ๋žŒ์ด ์žˆ๋‹ค๋ฉด ๋‚˜์˜ฌ ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ค๊ฐ€ ๋“ค์–ด๊ฐ!

๐Ÿช์›์ž์„ฑ์˜ ํ•„์š”

volatile bool _locked = false;

public void Acquire()
{
    while (_locked)
    {
        // ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ํ’€์–ด์ฃผ๊ธธ ๊ธฐ๋‹ค๋ฆฐ๋‹ค
    }
    
    // ๋‚ด๊บผ!
    _locked = true;
}

public void Release()
{
    _locked = false;
}

์ž๋ฌผ์‡ ๋ฅผ ๊ฑธ๊ณ  ๋“ค์–ด๊ฐ€ ์ž ๊ธˆ์ด ํ’€๋ฆฌ๊ธฐ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๋‚ด๊ฐ€ ๋“ค์–ด๊ฐ€๋ฉด ์ž๋ฌผ์‡ ๋กœ ์ž ๊ทผ๋‹ค

์‚ฌ์šฉ์„ ๋‹คํ•˜๋ฉด ์ž๊ธˆ์„ ํ’€๊ณ  ๋‚˜๊ฐ„๋‹ค

์–ธ๋œป๋ณด๋ฉด ์Šคํ•€๋ฝ์ด ์ž˜ ๊ตฌํ˜„๋œ๊ฒƒ ๊ฐ™์ง€๋งŒ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋Š” ์•ˆ๋‚˜์˜จ๋‹ค

  • ์ด์œ 
    • ๋ฌธ์„ ํ’€์–ด์ฃผ๊ธธ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ถ€๋ถ„๊ณผ ๋ฌธ์„ ์ž ๊ตฌ๋Š” ๋ถ€๋ถ„์ด ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌ ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ
    • ํ™”์žฅ์‹ค์— ๋‘๋ช…์ด ๋™์‹œ์— ๋“ค์–ด๊ฐ€์„œ ๋ฌธ์„ ์ž ๊ทธ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•จ!
    • ํ™”์žฅ์‹ค์— ๋“ค์–ด๊ฐ€๊ณ  ๋ฌธ์„ ์ž ๊ตฌ๋Š” ๊ฒƒ์€ ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌ ํ•ด์•ผ๋œ๋‹ค!!

๐ŸชInterlocked.Exchange

volatile int _locked = 0;

public void Acquire()
{
    while (true)
    {
        int original = Interlocked.Exchange(ref _locked, 1);
        if (original == 0) // ํ™”์žฅ์‹ค์— ์‚ฌ๋žŒ์ด ์—†์—ˆ๋‹ค๋ฉด original์€ 0์ด๊ณ  _locked์—๋Š” 1์ด ๋“ค์–ด๊ฐ
            break;
    }
}

public void Release()
{
    _locked = 0;
}
  • int original = Interlocked.Exchange(ref _locked, 1);ํ•ด์„
    • Interlocked.Exchange(ref _locked, 1)์€ _locked์— 1์„ ๋Œ€์ž…ํ•˜๋Š”๊ฒƒ
    • original์€ _locked์— 1์„ ๋Œ€์ž…ํ•˜๊ธฐ ์ „ ๋“ค์–ด์žˆ๋Š” ๊ฐ’
    • ํ™”์žฅ์‹ค์— ๋“ค์–ด๊ฐ€๊ณ ๋ฌธ์„ ์ž ๊ทธ๋Š” ๊ฒƒ์ด ์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌ!
original = _locked;
_locked = 1;
if (original == 0)
    break;

์›์ž์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋œ ๋ถ€๋ถ„์„ ํ’€์–ด์“ด๊ฒƒ

๐ŸชInterlocked.CompareExchange

  • CAD Compare - And - Swap ์—ฐ์‚ฐ
// CAD Compare - And - Swap ์—ฐ์‚ฐ

int expected = 0;
int desired = 1;
if (Interlocked.CompareExchange(ref _locked, desired, expected) == expected)
    break;
  • if (Interlocked.CompareExchange(ref _locked, desired, expected) == expected) ํ•ด์„
    • _locked๊ฐ€ expected์™€ ๊ฐ™์œผ๋ฉด desired๋ฅผ ๋Œ€์ž…ํ•˜๋ผ
    • ๋ฐ˜ํ™˜๊ฐ’์€ _locked์— ๋“ค์–ด์žˆ๋˜๊ฐ’
    • ๋ฐ˜ํ™˜๊ฐ’(์ด์ „๊ฐ’)์ด expected์™€ ๊ฐ™์œผ๋ฉด~~

๊ฐ’์„ ๋น„๊ตํ›„ ๊ฐ™์œผ๋ฉด ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ์—ฐ์‚ฐ๋ฒ• CAS์—ฐ์‚ฐ! (Compare - And - Swap)

Interlocked.Exchange๋ณด๋‹ค ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค

๐ŸชInterlocked.CompareExchange์„ ์‚ฌ์šฉํ•œ ์ „์ฒด์ฝ”๋“œ

namespace ServerCore
{
    class SpinLock
    {
        volatile int _locked = 0;

        public void Acquire()
        {
            while (true)
            {
                // CAD Compare - And - Swap
                int expected = 0;
                int desired = 1;
                if (Interlocked.CompareExchange(ref _locked, desired, expected) == expected)
                    break;
            }
        }

        public void Release()
        {
            _locked = 0;
        }
    }

    class Program
    {
        static int _num = 0;
        static SpinLock _lock = new SpinLock();

        static void Thread_1()
        {
            for (int i = 0; i < 100000; i++)
            {
                _lock.Acquire();
                _num++;
                _lock.Release();
            }
        }

        static void Thread_2()
        {
            for (int i = 0; i < 100000; i++)
            {
                _lock.Acquire();
                _num--;
                _lock.Release();
            }
        }

        static void Main(string[] args)
        {
            Task t1 = new Task(Thread_1);
            Task t2 = new Task(Thread_2);

            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(_num);
        }
    }
}

ํƒœ๊ทธ:

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ: