리소스를 할당한 순서를 역순으로 해제해야하는 이유

searchortype·2023년 4월 8일
1
post-thumbnail

25. 리소스 사용의 균형

TIP 35 : 시작한 것은 끝내라

중첩 할당

  • 리소스를 할당한 순서의 반대로 해제하라. 이렇게 해야 한 리소스가 다른 리소스를 참조하는 경우에도 리소스를 고아로 만들지 않는다.
  • 코드의 여러 곳에서 동일한 리소스 집합을 할당하는 경우, 할당 순서를 언제나 같게 하라. 교착 (deadlock) 가능성이 줄어들 것이다.

이를 더 잘 이해하기 위해 다음 예제를 보자.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBStatementExample {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            // JDBC 드라이버 로드
            Class.forName("com.mysql.jdbc.Driver");
            // MySQL 데이터베이스에 연결
            String url = "jdbc:mysql://localhost:3306/mydatabase";
            String username = "root";
            String password = "mypassword";
            connection = DriverManager.getConnection(url, username, password);
            // Statement 생성
            statement = connection.createStatement();
            // SELECT 쿼리 실행
            String query = "SELECT * FROM mytable";
            resultSet = statement.executeQuery(query);
            // 결과 처리
            while (resultSet.next()) {
                // 결과 가져오기
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                // 결과 처리
                System.out.println(id + ", " + name);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close(); // 할당된 ResultSet 해제
                }
                if (statement != null) {
                    statement.close(); // 할당된 Statement 해제
                }
                if (connection != null) {
                    connection.close(); // 할당된 데이터베이스 커넥션 해제
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

위 예제는 JDBC를 사용하여 MySQL 데이터베이스에 연결하고, SELECT 쿼리를 실행하는 코드이다.

JDBC 드라이버를 로드하고, DriverManager.getConnection() 메소드를 사용하여 MySQL 데이터베이스에 연결한다. 연결이 성공하면 connection 변수에 할당된다. 이후 connection.createStatement() 메소드를 사용하여 statement 변수에 Statement를 생성하고 statement.executeQuery() 메소드를 사용하여 SELECT 쿼리를 실행하고, 결과를 resultSet 변수에 할당한다. 이후 resultSet.next() 메소드를 사용하여 결과를 하나씩 가져오고, 각 결과를 처리하는 작업을 수행한다.

finally 블록에서는 할당된 리소스를 해제한다. ResultSet, Statement, Connection 변수에 할당된 리소스를 각각 close() 메소드를 리소스 할당 역순으로 호출하여 해제한다. 이렇게 함으로써 교착 (deadlock) 가능성이 줄인다.

역순으로 리소스할당을 해제하지 않으면 어떻게 될까?

Statement와 ResultSet이 먼저 해제되어 데이터베이스 연결이 끊어진 상태에서 리소스가 해제되기 때문에, 이후 다시 데이터베이스 연결을 사용할 수 없게 된다.

역순으로 리소스할당을 해제했음에도 데드락에 걸리는 경우는 어떤 경우일까?

  1. 리소스 할당과 해제가 다른 스레드에서 이루어지는 경우
    리소스를 할당한 스레드가 아닌 다른 스레드에서 리소스를 해제하는 경우, 데드락이 발생할 가능성이 있다.

  2. 리소스를 공유하는 경우
    다수의 스레드가 하나의 리소스를 공유하는 경우, 리소스의 할당 및 해제 순서만으로는 데드락을 예방할 순 없다.

  3. 스레드 우선순위의 변경
    스레드 우선순위를 변경하는 경우, 리소스의 할당 및 해제 순서만으로는 데드락을 예방할 수 없다.


reference

http://www.yes24.com/Product/Goods/12501565

0개의 댓글