[Java] Thread 2 ๐Ÿฆ„๐Ÿด

soyeonยท2022๋…„ 7์›” 15์ผ
0
post-thumbnail

Thread์˜ ๋™๊ธฐํ™”

: ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ thread๊ฐ€ ๊ณต์šฉ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

ex) ์˜ํ™” ์ขŒ์„ ์ •๋ณด
์—ฌ๋Ÿฌ ๊ฐœ์˜ thread๊ฐ€ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•  ๋•Œ ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ•œ ์‚ฌ๋žŒ์ด ์˜ํ™” ์ขŒ์„์„ ์˜ˆ๋งคํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ๊ฒฐ์ œ์™„๋ฃŒ๋ฅผ ํ•˜๋ฉด ์ž๋ฆฌ๋ฅผ ๋บ๊ธด๋‹ค.
์˜ํ™” ์ขŒ์„ ์ •๋ณด

=> T1 thread๊ฐ€ ๊ฒฐ์ œ๋ฅผ ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ thread์—์„œ writing์„ ํ•  ์ˆ˜ ์—†๊ฒŒ ํ•ด์ค˜์•ผ ํ•œ๋‹ค.
=> Critical Section (์ž„๊ณ„ ์˜์—ญ)์„ ์„ค์ •ํ•œ๋‹ค.
-> Lock(Monitor) ๊ฐœ๋… ๋“ฑ์žฅ
: T1 thread๊ฐ€ ์‚ฌ์šฉํ•  ๋•Œ๋Š” Lock์„ ๊ฐ€์ ธ๊ฐ€๊ฒŒ ๋˜๋ฉด์„œ ์ž„๊ณ„ ์˜์—ญ์„ ์„ค์ •ํ•œ๋‹ค. T1 thread๊ฐ€ Lock์„ ๋‹ค ์“ด ํ›„์—๋Š” ๋Œ๋ ค์ค€๋‹ค. ๋Œ€๊ธฐํ•˜๋˜ thread๋“ค ์ค‘ ํ•˜๋‚˜์˜ thread๊ฐ€ Lock์„ ์žก๋Š”๋‹ค.

๋™๊ธฐํ™” ๋ฌธ์ œ ์˜ˆ์ œ ์ฝ”๋“œ

  • ์€ํ–‰ ๊ณ„์ขŒ๋ฅผ ๊ณต์šฉ ๊ฐ์ฒด๋กœ ๋งŒ๋“ ๋‹ค.
package lecture0715;

// Thread์— ์˜ํ•ด์„œ ๊ณต์œ ๋˜๋Š” ๊ณต์œ  ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ class
class Account {
	
	private int balance = 1000;  // ๊ณ„์ขŒ ์ž”์•ก

	public int getBalance() {
		return balance;
	}
	
	// ์ถœ๊ธˆํ•˜๋Š” method
	public void withdraw(int money) {
		if(balance >= money) {
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				// TODO: handle exception
			}
			balance -= money;
		}
	}
}

class ThreadEx_09 implements Runnable {
	
	Account acc = new Account();
	
	@Override
	public void run() {
		while(acc.getBalance() > 0) {
			int money = (int)(Math.random() * 3 + 1) * 100;  // 100๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ํฌ๊ณ  400๋ณด๋‹ค ์ž‘์€ ์ •์ˆ˜
			acc.withdraw(money);
			System.out.println("๋‚จ์€ ์ž”์•ก์€ : " + acc.getBalance());			
		}
	}
}

public class ThreadExam09 {
	
	public static void main(String[] args) {
		
		ThreadEx_09 r = new ThreadEx_09();
		
		Thread t1 = new Thread(r);
		Thread t2 = new Thread(r);
		
		t1.start();
		t2.start();
	}
}

: ๋‘๊ฐœ์˜ ์ฝ”๋“œ๊ฐ€ ๋™์‹œ์— ์ง„์ž…ํ•ด์„œ ๋™์‹œ์— ๊ณ„์ขŒ์˜ ๋ˆ์„ ์ถœ๊ธˆํ•˜๊ฒŒ ๋œ๋‹ค.

Java์—์„œ Lock์„ ์–ป์–ด์„œ ์ž„๊ณ„ ์˜์—ญ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

synchronized

: ๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธํ•œ๋‹ค.

  • method ๋™๊ธฐํ™”

  • ๋™๊ธฐํ™” block์„ ์ƒ์„ฑ
    : ํšจ์œจ์ด ๋” ์ข‹๋‹ค.

synchronized ์ƒํƒœ ์ „์ด๋„

synchronized ์ƒํƒœ ์ „์ด๋„

synchronized ์˜ˆ์ œ ์ฝ”๋“œ

  1. method ๋™๊ธฐํ™”
package lecture0715;

// Thread์— ์˜ํ•ด์„œ ๊ณต์œ ๋˜๋Š” ๊ณต์œ  ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ class
class Account {
	
	private int balance = 1000;  // ๊ณ„์ขŒ ์ž”์•ก

	public int getBalance() {
		return balance;
	}
	
	// ์ถœ๊ธˆํ•˜๋Š” method => ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ
	public synchronized void withdraw(int money) {
		if(balance >= money) {
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				// TODO: handle exception
			}
			balance -= money;
		}
	}
}

class ThreadEx_09 implements Runnable {
	
	Account acc = new Account();
	
	@Override
	public void run() {
		while(acc.getBalance() > 0) {
			int money = (int)(Math.random() * 3 + 1) * 100;  // 100๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ํฌ๊ณ  400๋ณด๋‹ค ์ž‘์€ ์ •์ˆ˜
			acc.withdraw(money);
			System.out.println("๋‚จ์€ ์ž”์•ก์€ : " + acc.getBalance());			
		}
	}
}

public class ThreadExam09 {
	
	public static void main(String[] args) {
		
		ThreadEx_09 r = new ThreadEx_09();
		
		Thread t1 = new Thread(r);
		Thread t2 = new Thread(r);
		
		t1.start();
		t2.start();
	}
}

: method ์ž์ฒด๊ฐ€ ๋™๊ธฐํ™”๊ฐ€ ๋˜์—ˆ๋‹ค. ํ•˜๋‚˜์˜ thread๊ฐ€ method๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ thread๋Š” method๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ method ์•ˆ์—์„œ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์ผ๋ถ€๋ถ„์ด๋‹ค. method ์ž์ฒด๋ฅผ ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ ํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ์ ์ด๋‹ค.

  1. ๋™๊ธฐํ™” block์„ ์ƒ์„ฑ
package lecture0715;

// Thread์— ์˜ํ•ด์„œ ๊ณต์œ ๋˜๋Š” ๊ณต์œ  ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ class
class Account {
	
	private int balance = 1000;  // ๊ณ„์ขŒ ์ž”์•ก

	public int getBalance() {
		return balance;
	}
	
	// ์ถœ๊ธˆํ•˜๋Š” method => ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ
	public void withdraw(int money) {
		
		synchronized (this) {
			if(balance >= money) {
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					// TODO: handle exception
				}
				balance -= money;
			}
		}	
	}
}

class ThreadEx_09 implements Runnable {
	
	Account acc = new Account();
	
	@Override
	public void run() {
		while(acc.getBalance() > 0) {
			int money = (int)(Math.random() * 3 + 1) * 100;  // 100๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ํฌ๊ณ  400๋ณด๋‹ค ์ž‘์€ ์ •์ˆ˜
			acc.withdraw(money);
			System.out.println("๋‚จ์€ ์ž”์•ก์€ : " + acc.getBalance());			
		}
	}
}

public class ThreadExam09 {
	
	public static void main(String[] args) {
		
		ThreadEx_09 r = new ThreadEx_09();
		
		Thread t1 = new Thread(r);
		Thread t2 = new Thread(r);
		
		t1.start();
		t2.start();
	}
}

: ๋™๊ธฐํ™” ์ฒ˜๋ฆฌ ํ•  ๋ถ€๋ถ„๋งŒ ๋ธ”๋ก์œผ๋กœ ๋ฌถ์–ด์ค€๋‹ค.
mutex : ์–ด๋–ค ๊ฐ์ฒด๋ฅผ ๋™๊ธฐํ™” ํ• ์ง€ ์„ค์ •ํ•ด์ค€๋‹ค.

thread๊ฐ€ ๊ณต์œ ์ž์›์— ๋Œ€ํ•œ Lock์„ ํš๋“ํ•œ ํ›„ ์˜ค๋žœ ์‹œ๊ฐ„์„ ๋ณด๋‚ธ๋‹ค. -> ๋‹ค๋ฅธ thread๊ฐ€ ์ผ์„ ๋ชป ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๊ฐ€์ง€ method๊ฐ€ ์ œ๊ณต๋œ๋‹ค.
=> wait(), notify()

wait()

: Lock์„ ๋†“๊ณ  ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ„๋‹ค.

notify()

: ๋Œ€๊ธฐ ์ƒํƒœ์— ์žˆ๋Š” thread๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก block์„ ํ•ด์ œํ•œ๋‹ค.

์—ฐ์Šต ๋ฌธ์ œ

  1. 1์ดˆ๋งˆ๋‹ค ์ž์‹ ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•˜๋Š” thread๋ฅผ 2๊ฐœ ์ƒ์„ฑํ•œ๋‹ค. ๋‹จ, ์ด๋ฆ„์„ ์ถœ๋ ฅํ•  ๋•Œ ๊ต๋Œ€๋กœ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•œ๋‹ค.
  • ๋‚ด ์ฝ”๋“œ
package lecture0715;

class ThreadEx_10 implements Runnable {
	
	@Override
	public void run() {
		synchronized (this) {
			try {
				for(int i=0; i<20; i++) {
					this.notify();
					Thread.sleep(1000);
					System.out.println(Thread.currentThread().getName());
					this.wait();
				}
			} catch (Exception e) {
				
			}
		}		
	}
}

public class ThreadExam10 {

	public static void main(String[] args) {
		ThreadEx_10 r = new ThreadEx_10();
		
		Thread t1 = new Thread(r, "1 Thread");
		Thread t2 = new Thread(r, "2 Thread");
		
		t1.start();
		t2.start();
	}
}

๋๋‚˜์ง€ ์•Š๊ณ , ๊ณ„์†ํ•ด์„œ ์ถœ๋ ฅ๋˜๋Š” ๋ฌธ์ œ ๋ฐœ์ƒ

  • ์ •๋‹ต ์ฝ”๋“œ
package lecture0715;

class Shared {

    public synchronized void printNum() {    
        
        try {
            for(int i=0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " : " + i);
                notify();
                wait();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}

class ThreadEx_10 implements Runnable {
	
	private Shared shared;
    
    public ThreadEx_10(Shared shared) {
        this.shared = shared;
    }
    
    @Override
    public void run() {            
        shared.printNum();
    }        
}
public class ThreadExam10 {
	
	public static void main(String[] args) {
		Shared obj = new Shared();
        
        Thread t1 = new Thread(new ThreadEx_10(obj));
        Thread t2 = new Thread(new ThreadEx_10(obj));
        
        t1.setName("์ฒซ๋ฒˆ์งธ Thread!!");
        t2.setName("๋‘๋ฒˆ์งธ Thread!!");

        t1.start();
        t2.start();
	}
	
}

0๊ฐœ์˜ ๋Œ“๊ธ€