之前了解这些概念的时候不是十分理解,只是大概知道怎么回事,晚上很多教程都是说定义,乍一看需要花时间去理解,在这里谈谈我自己的理解(偏白话,不谈具体概念)
1.乐观锁悲观锁
乐观锁
乐观锁其实就是不上锁,只是加一些逻辑判断防止资源冲突覆盖,比如从网上找来的图:
如果双方在报名的时候数据是相同的,原数据都是5,此时客户端1更新,将数据更新为6,但此时客户端2并不知道数据已被更新,拿着过期的数据5去更新数据库,这时候就会将客户端1的数据覆盖掉,造成覆盖错误.
再举个例子:
我在网上上报了一些资料,发布之后发现里面有些错误想修改,这时候我的同事也发现错误想更改,我先改完提交,但此时我同事不知道以为我没有改,他提交的时候就会覆盖我刚刚提交的数据,造成覆盖.
所以为了防止覆盖错误,就需要在数据上进行加锁处理,但是如果真的加一把锁上去也完全没有必要,因为数据不是特别重要,而且出错的概率也比较小,最主要的错误也就是数据覆盖,所以就有了乐观锁,仅仅在数据更新的时候比较就可以,乐观锁的解决方案一般是版号机制,数据被更新一次版号就自增一次,提交的时候如果版号不对应,就说明有人在之前已经提交了更新提交.
还是上方的例子,引入版号的机制:
在我第一次提交时,初始化版号为0,如果我提交后发现数据有错项进行修改,在我提交后版号就会自增为1,同时我的同事拿着原始数据修改后也去提交,此时他本地的版号仍然为0,提交时就会发现版号不对应,就说明有人已经在他之前对数据进行了修改,不会进行覆盖.
悲观锁
相比于乐观锁,悲观锁是真的要上锁,定义不说了网上一大把,说说我自己的疑问:
以前操作数据库的时候,一直不明白数据库的悲观锁是如何进行操作的,什么行锁表锁等等,后来发现原来不需要自己操作,数据库的事务会自己进行操作,比如开启事务没提交时别人取得的数据还是未操作的,提交的的话会被事务卡住,是真正意义的禁止数据同时被修改.
java里的悲观锁是synchronized关键字等等实一些方法实现的,在关键资源加入锁机制后,可以真的保证同一数据只可以在同时被单一线程操作,从根本上禁止了数据错误的问题.
2.可重入锁和不可重入锁
可重入锁
以前一直以为可重入锁在Java中是一个具体的实现,具体的类,而且也不知道为什么叫可重入锁,后才才知道:可重入锁是一个类别,可重入锁就是指在一个锁锁住的区域,再次使用同一个锁对象去加锁,不会发生死锁.
比如java中的synchronized关键字也属于可重入锁.
public static void main(String[] args) {
synchronized (Test.class)
{
System.err.println("第一层锁");
synchronized (Test.class)
{
System.err.println("第二层锁");
synchronized (Test.class)
{
System.err.println("不会发生死锁");
}
}
}
}
可重入锁的特性就如此,重复使用一把锁上锁,不会死锁仍可进入,所以叫可重入.
我们一般编程中可能不会写出这样的代码,但是如果所分散在不同方法的情况还是会出现的,可重入锁此时就保证了以下情况不会死锁.
public class Test {
public static void main(String[] args) {
synchronized (Test.class)
{
System.err.println("第一层锁");
method1();
}
}
public static void method1()
{
synchronized (Test.class)
{
System.err.println("第二层锁");
method2();
}
}
public static void method2()
{
synchronized (Test.class)
{
System.err.println("不会发生死锁");
}
}
}
不可重入锁
顾名思义,不可以在锁中再次获取锁,以上情况会死锁.