1

Main.java のコード:

public class Main {
    public static void main(String[] args) {
        final ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");

        final UserManager userManager = (UserManager) ctx.getBean("userManagerImpl");

        new Thread() {
            public void run() {
                User user = new User();
                user.setUsername("hari18");
                user.setName("haris1");

                userManager.insertUser(user);

                System.out.println("User inserted!");
            }
        } .start();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread() {
            public void run() {
                List<User> users = userManager.getUsers();
                System.out.println("\nUser list fetched!" + "\nUser count: " + users.size());
                for (User user1 : users) {
                    System.out.println(user1.getUsername());
                }
            }
        } .start();
    }
}    

UserManagerImpl.java のコード:

@Service
@Scope("prototype")
public class UserManagerImpl implements UserManager {
    @Autowired
    private UserDAO userDAO;

    @Override
    @Transactional( propagation=Propagation.REQUIRED , isolation=Isolation.SERIALIZABLE)
    public void insertUser(User user) {
        userDAO.insertUser(user);
    }

    @Override
    @Transactional( propagation=Propagation.REQUIRED , isolation=Isolation.SERIALIZABLE)
    public List<User> getUsers() {
        return userDAO.getUsers();
    }
}

UserDAOImpl.java のコード:

@Service
public class UserDAOImpl extends JdbcDaoSupport implements UserDAO {
    @Autowired
    public UserDAOImpl(DataSource dataSource) {
        setDataSource(dataSource);
    }

    @Override
    public void insertUser(User user) {
        getJdbcTemplate().update("INSERT INTO USER (USERNAME, NAME) VALUES (?, ?)",
            new Object[] {
                user.getUsername(),
                user.getName()
            }
        );

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<User> getUsers() {
        List<User> users = getJdbcTemplate().query("SELECT * FROM USER",new UserMapper());
        return users;
    }
}    

spring.xml のコード:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <tx:annotation-driven transaction-manager="transactionManager"/>

    <context:component-scan base-package="com.byteslounge.spring" />
    <!-- context:component-scan base-package="com.byteslounge.spring" /-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="password" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
        <property name="dataSource" ref="dataSource" />
    </bean>

</beans>

上記のメインクラスを実行すると、理論的にはスレッド 1 が最初に開始され、テーブルをロックする必要がありますUSER(なぜなら)。スレッド 2 が実行されているときは、テーブルからテーブルを読み取らずにテーブルからisolation = Isolation.SERIALIZABLEロックが解放されるまで待機する必要がありますが、実行するとUSERこのコードは、最初のトランザクションが完了するのを待たずにテーブルと印刷を読み取っています。USERIsolation だと思っていてもテーブルロックが効かないのはなぜSERIALIZABLE???

4

2 に答える 2

1

この質問に対する答えを得ました。ここでの問題は、スレッド 1 とトウの間の時間遅延でした。ここでは時間遅延を 100 ミリ秒と指定しましたが、insertUser() がテーブル ロックを取得する前に getUsers() がロックを占有し、データを取得して処理するため、この遅延は十分ではありません。この問題は解決されたため、時間遅延を 1000ms に変更しました。そのため、insertUser() はロックを占有し、getUsers() は insertUser() が終了して挿入部分をコミットするまで待機しました。

于 2013-09-11T14:18:33.650 に答える