JAVA 42일차

이희복·2023년 2월 27일
0

JAVA

목록 보기
3/41

아래의 네트웍 객체에 대하여 설명하시오.

URLConnection

  • Application과 URL간의 통신링크를 위한 작업을 수행한다

InetAdrress

  • IP 주소를 표현한다

Socket

  • 두 프로그램이 서로 데이터를 주고 받을 수 있도록 양쪽(사용자 - 서버)에 생성되는 통신 단자이다

SeverSocket

  • 클라이언트가 연결 요청을 하면 accept() 메서드로 연결 수락, 통신용 socket 생성한다

아래를 실행보고, balance 가 마이너스 금액이 찍히는 이유를 적고

코드를 수정해 보시오.
class Ex13_12 {
public static void main(String args[]) {
Runnable r = new RunnableEx12();
new Thread(r).start(); // ThreadGroup에 의해 참조되므로 gc대상이 아니다.
new Thread(r).start(); // ThreadGroup에 의해 참조되므로 gc대상이 아니다.
}
}

class Account {
private int balance = 1000;

public  int getBalance() {
	return balance;
}

public void withdraw(int money){
	if(balance >= money) {
		try { Thread.sleep(1000);} catch(InterruptedException e) {}
		balance -= money;
	}
} // withdraw

}

class RunnableEx12 implements Runnable {
Account acc = new Account();

public void run() {
	while(acc.getBalance() > 0) {
		// 100, 200, 300중의 한 값을 임으로 선택해서 출금(withdraw)
		int money = (int)(Math.random() * 3 + 1) * 100;
		acc.withdraw(money);
		System.out.println("balance:"+acc.getBalance());
	}
} // run()

}

balance(잔액) thread-safe가 되지 않았기 때문에 스레드가 잔액을 삭감하기 전에 balance(잔액)에 접근해 삭감을 해버리고 다시 이 sleep()에서 깨어나 balance(잔액) 을 삭감해버리기 때문에 잔액이 0 이하의 마이너스 값을 가지게 된다.

class T2 {
public static void main(String args[]) {
Runnable r = new RunnableEx12();
new Thread(r).start(); // ThreadGroup에 의해 참조되므로 gc대상이 아니다.
new Thread(r).start(); // ThreadGroup에 의해 참조되므로 gc대상이 아니다.
}
}

class Account {
private int balance = 1000;

public  int getBalance() {
	return balance;
}

synchronized public void withdraw(int money){
	if(balance >= money) {
		try { Thread.sleep(1000);} catch(InterruptedException e) {}
		balance -= money;
	}
} // withdraw

}

class RunnableEx12 implements Runnable {
Account acc = new Account();

public void run() {
	while(acc.getBalance() > 0) {
		// 100, 200, 300중의 한 값을 임으로 선택해서 출금(withdraw)
		int money = (int)(Math.random() * 3 + 1) * 100;
		acc.withdraw(money);
		System.out.println("balance:"+acc.getBalance());
	}
} // run()

}

해결하는 방법은 간단합니다.
공유데이터에 대한 접근과 수정이 이루어지는 메서드에 synchronized 키워드를 리턴타입 앞에 붙여주면 됩니다. 스레드가 먼저 공유데이터나 메서드에 점유하고 있는 상태인 경우 block으로 처리하기 때문에 이외의 스레드의 접근을 막는다.

0개의 댓글