2015-12-18 103 views
0

我写了一个Java应用程序,其中不同的线程(每个线程都有一个使用连接池c3p0的自己的连接对象)调用这样的方法。Java MySQL可能导致死锁?

伪代码:

void example(Connection connection) { 
    connection.update("LOCK TABLES Test WRITE"); 
    resultSet = connection.query("SELECT * FROM Test WHERE Id = '5'"); 

    if (resultSet.next()) { 
     connection.update("UPDATE Test SET Amount = '10' WHERE Id = '5'"); 
    } else { 
     connection.update("INSERT INTO Test (Id, Amount) VALUES ('5', '10')"); 
    } 

    connection.update("UNLOCK TABLES"); 
    connection.commit(); 
} 

有其锁定表,选择/更新/插入的东西,然后解开表中的其他一些类似的方法。目的是防止竞争状况和僵局。

当我从不同线程调用这种方法时,是否有可能导致MySQL死锁?如果是的话,你能举个例子说明这是怎么发生的(导致死锁的两个交易的时间)?我是一个僵局的小白,我想进入这个领域。

编辑:明确应该在方法中使用的连接是从调用该方法的线程传递的。

编辑:将READ替换为WRITE

+0

我假设“update()”和“query()”方法使用相同的连接(而不是从池中获取新的连接)。 – slambeth

+0

@slambeth是的,调用方法的线程从池中获取连接对象并将其传递给方法。该方法中的整个代码使用此连接。 autoCommit是错误的。 – stonar96

+0

@Jas是的,我使用InnoDB。 – stonar96

回答

1

它不能在这里。由于没有复杂的逻辑,代码在更新后立即提交,因此必须始终有一个经过的线程。即使在更复杂的情况下,它可能需要最高的序列化级别(可重复读取),我相信MySql不支持。

1

这可能会造成死锁。其实我不确定它是否会执行,因为你需要获得一个“写”锁,而不是“读”。

+0

你是对的,但我认为我必须防止(READ和WRITE)来防止竞争条件。 – stonar96

+0

锁定类型标识不能识别其他会话可以执行的操作,它识别“你”可以做什么。 “WRITE”是更高级别的锁定 - 它允许您编写并完全禁止其他会话访问: – slambeth

+0

http://dev.mysql.com/doc/refman/5.7/en/lock-tables.html – slambeth