Java乐观锁的实现原理(案例)

本文介绍了一种基于乐观锁机制的并发控制方案,并通过一个具体的Java示例演示如何使用版本号来避免多线程环境下产生的脏数据。代码示例展示了如何在多线程环境下更新文件内容的同时确保数据一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://www.what21.com/sys/view/java_java-thread_1458012669389.html

有2种机制可以解决这个问题:就是悲观锁和乐观锁了。

这里我们使用乐观锁,通过案例代码来实现一个乐观锁,达到解决问题的目的。

package what21.thread.lock;
 
public class OptimLockMain {
 
    // 文件版本号
    static int version = 1;
    // 操作文件
    static String file = "d://IT小奋斗.txt";
     
    /**
     * 获取版本号
     * 
     * @return
     */
    public static int getVersion(){
        return version;
    }
     
    /**
     * 更新版本号
     */
    public static void updateVersion(){
        version+=1;
    }
     
    /**
     * @param args
     */
    public static void main(String[] args) {
        for(int i=1;i<=5;i++){
             new OptimThread(String.valueOf(i),getVersion(),file).start();
        }
    }
     
}

package what21.thread.lock;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class OptimThread extends Thread {
 
    // 文件版本号
    public int version;
    // 文件
    public String file;
     
    public OptimThread(String name,int version,String file){
        this.setName(name);
        this.version = version;
        this.file = file;
    }
     
    public void run() {
        // 1. 读取文件
        String text = read(file);
        println("线程"+ getName() + ",文件版本号为:" + OptimLockMain.getVersion());
        println("线程"+ getName() + ",版本号为:" + getVersion());
        // 2. 写入文件
        if(OptimLockMain.getVersion() == getVersion()){
            println("线程" + getName() + ",版本号为:" + version + ",正在执行");
            // 文件操作,这里用synchronized就相当于文件锁
            // 如果是数据库,相当于表锁或者行锁
            synchronized(OptimThread.class){
                if(OptimLockMain.getVersion() == this.version){
                    // 写入操作
                    write(file, text);
                    // 更新文件版本号
                    OptimLockMain.updateVersion();
                    return ;
                }
            }
        }
        // 3. 版本号不正确的线程,需要重新读取,重新执行
        println("线程"+ getName() + ",文件版本号为:" + OptimLockMain.getVersion());
        println("线程"+ getName() + ",版本号为:" + getVersion());
        System.err.println("线程"+ getName() + ",需要重新执行。");
    }
 
    /**
     * @return
     */
    private int getVersion(){
        return this.version;
    }
     
    /**
     * 写入数据
     * 
     * @param file
     * @param text
     */
    public static void write(String file,String text){
        try {
            FileWriter fw = new FileWriter(file,false);
            fw.write(text + "\r\n");
            fw.flush();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
     
    /**
     * 读取数据
     * 
     * @param file
     * @return
     */
    public static String read(String file){
        StringBuilder sb = new StringBuilder();
        try {
            File rFile = new File(file);
            if(!rFile.exists()){
                rFile.createNewFile();
            }
            FileReader fr = new FileReader(rFile);
            BufferedReader br = new BufferedReader(fr);
            String r = null;
            while((r=br.readLine())!=null){
                sb.append(r).append("\r\n");
            }
            br.close();
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }
     
    /**
     * @param content
     */
    public static void println(String content){
        System.out.println(content);
    }
     
}

1、这里线程对文件写入的操作,就相当于修改表中的一条数据。

2、多个线程需要对这个文件写入时,同时只能有一个线程写入该文件。

3、同时只能有一个线程写入文件,就相当于与表的行锁,同一时间只允许一个线程操作。

4、线程初始化时,持有相同的版本号,写入文件操作完成后,然后变更版本号。

5、其他线程再次操作时,比较版本号,版本号较低的不在进行写入操作,或者抛出异常,或者再次执行该操作,这样就防止产生脏数据了。









评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值