悲观锁--【DRP】

分销商的主键采用了单独的表来完成,因为多个用户同时生成主键,那么就存在访问共享资源的情况,必须保持线程同步。

两种解决方案:

1)java中使用关键字synchronized关键字对方法同步

2)可以使用数据库的悲观锁,例如:select value from t_table_id where table_name=? for update;

左侧的再输入悲观锁语句,就不能查询出数据来了。

悲观锁:

整个数据处理的过程,数据对外界的修改持保守态度。整个数据处理过程中,处于锁定的状态。本次事务提交之前,外界无法修改该记录。体现了数据库的独占性。

乐观锁:

基于版本标识来实现的。读数据时候,将版本号读出,修改之后,对其版本号加1。提交的时候,将提交数据的版本数据和数据库中的版本号对比,大于数据库中的版本,予以提交。

 所以源代码的语句:

/**
 * 
 */
package com.bjpowernode.drp.util;

import java.awt.image.ConvolveOp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @ClassName:IdGenerator
 * @Description:ID生成器
 * @author wm
 * @date 2016年1月15日下午6:41:06
 */
public class IdGenerator {
    /**
     * 根据表名生成该表的序列
     * @param tableName
     * @return 返回生成的序列
     * 使用synchronized实现线程同步问题
     */
    //锁住线程1
    //public static synchronized int  generate(String tableName){
    public  int  generate(String tableName){
        //TODO:id 生成器
        //锁住线程2
        /*synchronized (this) {
            
        }*/
        //数据库的悲观锁
        String sql="select value from t_table_id where table_name=? for update";
        Connection conn =null;
        PreparedStatement pstmt=null;
        ResultSet rs=null;
        int value=0;
        try {
            conn=DbUtil.getConnection();
            pstmt=conn.prepareStatement(sql);
            pstmt.setString(1, tableName);
            rs=pstmt.executeQuery();
            if(!rs.next()){
                throw new RuntimeException();
            }
            value =rs.getInt("value");
            value++;
            modifyValueField(conn,tableName,value);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }finally{
            DbUtil.close(rs);
            DbUtil.close(pstmt);
            DbUtil.close(conn);
        }
        
        return value;
    }
    
    /**
     * 根据表名更新序列字段的值
     * @param conn
     * @param tableName
     * @param value
     * @throws SQLException 
     */
    private static  void modifyValueField(Connection conn,String tableName,int value) throws SQLException{
        String sql="update t_table_id set value=? where table_name=?";
        PreparedStatement pstmt=null;
        try {
            pstmt=conn.prepareStatement(sql);
            pstmt.setInt(1, value);
            pstmt.setString(2, tableName);
            pstmt.executeUpdate();
        } finally{
            DbUtil.close(pstmt);
        }
    }
    
    
    public static void main(String[] args){
        //完成测试
        int retValue=IdGenerator.generate("t_client");
        System.out.println(retValue);
    }
}
原文地址:https://www.cnblogs.com/wangmei/p/5135834.html