设计两个线程,一个线程对数据设置为悲观锁,并在提交之前暂停,另一个线程去操作同一个数据
乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据;如果别人修改了数据则放弃操作,否则执行操作。
悲观锁:对一个数据加了乐观锁(即select后加了for update),
其他线程对此数据进行修改时,需要等待前一个线程完成之后才能进行
即:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
将数据设置为悲观锁
package com.Jdbc;
import com.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 乐观锁:多个线程对一个数据进行修改,刚开始线程A,B都读到版本是1.0,线程A修改成了1.2,
* 此刻线程B想修改成1.1,再次读的时候发现版本是1.2,直接回滚。
*
* 悲观锁:对一个数据加了乐观锁(即select后加了for update),
* 其他线程对此数据进行修改时,需要等待前一个线程完成之后才能进行
*开启一个事务,专门进行查询,并且使用行级锁/悲观锁
*/
public class test09 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql = "select userName from smbms_user where userCode = ? for update "; //行级锁,悲观锁
ps = conn.prepareStatement(sql);
//设置值
ps.setString(1,"zhaoyan");
rs = ps.executeQuery();
while (rs.next()){
System.out.println(rs.getString("userName"));
}
//提交事务
conn.commit();
}catch (Exception e){
//回滚事务
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
try {
JdbcUtils.release(conn,ps,rs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
另外一个线程来修改,发现,如果上一个线程未完成,则一直处于等地状态,直到上一个线程对其数据操作完毕
package com.Jdbc;
import com.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 这个负责修改被锁定的程序
*/
public class test07 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = JdbcUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
String sql = "update smbms_user set userName = ? where userCode = ? "; //行级锁,悲观锁
ps = conn.prepareStatement(sql);
//设置值
ps.setString(1,"悲观锁");
ps.setString(2,"zhaoyan");
int i = ps.executeUpdate();
while (i>1){
System.out.println(rs.getString("userName"));
}
//提交事务
conn.commit();
}catch (Exception e){
//回滚事务
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
try {
JdbcUtils.release(conn,ps,rs);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}