锁,当多个事务同时对数据库表中的同一条数据操作时,如果没有加锁机制的话,就会产生脏数据(duty data)。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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();
         }
     }
     
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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、其他线程再次操作时,比较版本号,版本号较低的不在进行写入操作,或者抛出异常,或者再次执行该操作,这样就防止产生脏数据了。

Java乐观锁的实现原理(案例)相关推荐

  1. Java乐观锁的实现原理和典型案例

    Java乐观锁的实现原理 什么是乐观锁? 在并发编程中,多个线程同时对同一资源进行操作时,需要使用锁来保证数据的一致性. 乐观锁与悲观锁是两种不同的锁机制. 悲观锁会在整个操作期间占用资源的独占性,以 ...

  2. java乐观锁实现_Java 乐观锁原理与实战演练

    原标题:Java 乐观锁原理与实战演练 一. 前言 最近在做一个简单审批流程的项目,由于只有固定二级审批所以没有工作流组件,然后就遇到一个审批节点捞单时候,多个人同时审批时候如何保证业务正常运行的问题 ...

  3. Java 乐观锁和悲观锁

    文章目录 Java 乐观锁和悲观锁 1.悲观锁 2.乐观锁 2.1 CAS 2.2 模拟CAS算法 2.3 JUC 2.4 CAS中的ABA问题 2.5 使用CAS会引发的问题 Java 乐观锁和悲观 ...

  4. java乐观锁实现案例

    简单说说乐观锁.乐观锁是相对于悲观锁而言.悲观锁认为,这个线程,发生并发的可能性极大,线程冲突几率大,比较悲观.一般用synchronized实现,保证每次操作数据不会冲突.乐观锁认为,线程冲突可能性 ...

  5. 【mysql】悲观锁和乐观锁的实现原理

    java多线程中的锁分类多种多样,其中有一种主要的分类方式就是乐观和悲观进行划分的. 一.乐观锁概念 说是写乐观锁的概念,但是通常乐观锁和悲观锁的概念都要一块写.对比着来才更有意义. 1.悲观锁概念 ...

  6. java 乐观锁 实例_JAVA乐观锁实现-CAS(示例代码)

    是什么 全称compare and swap,一个CPU原子指令,在硬件层面实现的机制,体现了乐观锁的思想. JVM用C语言封装了汇编调用.Java的基础库中有很多类就是基于JNI调用C接口实现了多线 ...

  7. Java 乐观锁 悲观锁

    一.乐观锁.悲观锁定义 乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据.因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行 ...

  8. java 乐观锁和悲观锁,Threadlocal

    7.乐观锁和悲观锁 悲观锁(Pessimistic Lock)顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到 ...

  9. 乐观锁-基于CAS原理

    乐观锁理论基础 乐观锁的操作过程中其实没有没有任何锁的参与,乐观锁只是和悲观锁相对,严格的说乐观锁不能称之为锁.下面我们就通过乐观锁与悲观锁的对比来更好的理解乐观锁. 乐观锁与悲观锁的概念 乐观锁:总 ...

最新文章

  1. 蚂蚁金服核心技术:百亿特征实时推荐算法揭秘
  2. cplus cjson 封装
  3. 【剑指offer-Java版】30最小的K个数
  4. 在Linux下记录所有用户的登录和操作日志
  5. ocx可以被Java调用么_java调用ocx
  6. 20155320《网络对抗》Exp4 恶意代码分析
  7. 返回一个不确定的对象_我有一个Android必备知识点,你确定不了解一下?
  8. java实现支付宝第三方登录_Java 实现QQ第三方登录(附赠:完整代码)
  9. JavaScript中尺寸、坐标
  10. bak 服务器备份文件怎么恢复,bak文件怎么还原
  11. python base_Python base(一)
  12. 快速计算某一天是星期几-蔡勒公式
  13. 【开赛啦!邀你来战 】2022年“桂林银行杯”数据建模大赛暨全国大学生数学建模竞赛广西赛区热身赛
  14. 凡拓数字通过注册:年营收7亿 伍穗颖夫妇控制43%股权
  15. HTML5 Canvas核心技术迷你书
  16. 环境保护刻不容缓,智慧治理迎来新生!
  17. 阿里云服务器使用SMTP发送邮件
  18. 计算机操作 操作鉴定试题及答案,计算机操作员初级试题及答案
  19. 新旧笔记本电脑怎么样转移数据?换电脑数据如何迁移
  20. linux superblock 时间,e2fsck: Bad magic number in super-block_Linux

热门文章

  1. C++ 函数返回数组处理方法
  2. html input样式优化,CSS Input 样式美化
  3. pycharm社区版使用database navigator(DB Browser)
  4. 面试屡屡碰壁,痛定思痛闭关修炼!半年后4面阿里成功拿offer
  5. [scRNA-seq]doublets检测——DoubletFinder scrublet (下)
  6. 基于Halcon学习的一维码识别【四】barcode.param_contrast.hdev
  7. keras如何在验证集加噪声_如何使自定义高斯噪声层对Keras中的每一列数据施加不同的stddev?...
  8. 2010.4 计算机二级等级考试 vb上机试题 第一套 的答案,2010年4月计算机二级等级考试VB上机考试第一套.docx...
  9. 职中选什么专业好_读职中选什么专业比较好就业
  10. 千年止咳秘方“秋梨膏”家庭自制法