java replace [ 一文足以了解什么是 Java 中的锁

java replace [ 一文足以了解什么是 Java 中的锁

Java 锁分类

Java 中的锁有很多,可以按照不同的功能、种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述

java replace [

下面我们依次对各个锁的分类进行详细阐述。

线程是否需要对资源加锁

Java 按照是否对资源加锁分为乐观锁和悲观锁,乐观锁和悲观锁并不是一种真实存在的锁,而是一种设计思想,乐观锁和悲观锁对于理解 Java 多线程和数据库来说至关重要,下面就来探讨一下这两种实现方式的区别和优缺点

悲观锁

悲观锁是一种悲观思想,它总认为最坏的情况可能会出现,它认为数据很可能会被其他人所修改,所以悲观锁在持有数据的时候总会把资源 或者 数据 锁住java replace [ 一文足以了解什么是 Java 中的锁,这样其他线程想要请求这个资源的时候就会阻塞,直到等到悲观锁把资源释放为止。传统的关系型数据库里边就用到了很多这种锁机制,**比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。**悲观锁的实现往往依靠数据库本身的锁功能实现。

Java 中的 和 等独占锁(排他锁)也是一种悲观锁思想的实现,因为 和 不管是否持有资源,它都会尝试去加锁,生怕自己心爱的宝贝被别人拿走。

乐观锁

乐观锁的思想与悲观锁的思想相反,它总认为资源和数据不会被别人所修改,所以读取不会上锁,但是乐观锁在进行写入操作的时候会判断当前数据是否被修改过(具体如何判断我们下面再说)。乐观锁的实现方案一般来说有两种:版本号机制 和 CAS实现 。乐观锁多适用于多读的应用类型,这样可以提高吞吐量。

在Java中

java.util..包下面的原子变量类就是使用了乐观锁的一种实现方式 CAS 实现的。

两种锁的使用场景

java replace [

上面介绍了两种锁的基本概念,并提到了两种锁的适用场景,一般来说,悲观锁不仅会对写操作加锁还会对读操作加锁,一个典型的悲观锁调用:

select * from student where name="cxuan" for update

这条 sql 语句从 表中选取 name = "cxuan" 的记录并对其加锁,那么其他写操作再这个事务提交之前都不会对这条数据进行操作,起到了独占和排他的作用。

悲观锁因为对读写都加锁java replace [ 一文足以了解什么是 Java 中的锁,所以它的性能比较低,对于现在互联网提倡的三高(高性能、高可用、高并发)来说java replace [,悲观锁的实现用的越来越少了,但是一般多读的情况下还是需要使用悲观锁的,因为虽然加锁的性能比较低,但是也阻止了像乐观锁一样,遇到写不一致的情况下一直重试的时间。

相对而言,乐观锁用于读多写少的情况,即很少发生冲突的场景,这样可以省去锁的开销,增加系统的吞吐量。

乐观锁的适用场景有很多,典型的比如说成本系统java replace [,柜员要对一笔金额做修改,为了保证数据的准确性和实效性,使用悲观锁锁住某个数据后,再遇到其他需要修改数据的操作,那么此操作就无法完成金额的修改,对产品来说是灾难性的一刻,使用乐观锁的版本号机制能够解决这个问题,我们下面说。

乐观锁的实现方式

乐观锁一般有两种实现方式:采用版本号机制 和 CAS(-and-Swap,即比较并替换)算法实现。

版本号机制

版本号机制是在数据表中加上一个 字段来实现的,表示数据被修改的次数,当执行写操作并且写入成功后, = + 1,当线程A要更新数据时,在读取数据的同时也会读取 值,在提交更新时,若刚才读取到的 值为当前数据库中的值相等时才更新,否则重试更新操作,直到更新成功。

我们以上面的金融系统为例,来简述一下这个过程。

java replace [

上面两种情况是最乐观的情况,上面的两个事务都是顺序执行的,也就是事务一和事务二互不干扰,那么事务要并行执行会如何呢?

java replace [

事务一开启,男柜员先执行读操作,取出金额和版本号,执行写操作

begin
update 表 set 金额 = 120,version = version + 1 where 金额 = 100 and version = 0

java replace [

此时金额改为 120,版本号为1,事务还没有提交

事务二开启,女柜员先执行读操作,取出金额和版本号,执行写操作

begin
update 表 set 金额 = 50,version = version + 1 where 金额 = 100 and version = 0

此时金额改为 50,版本号变为 1,事务未提交

现在提交事务一,金额改为 120,版本变为1,提交事务。理想情况下应该变为 金额 = 50,版本号 = 2,但是实际上事务二 的更新是建立在金额为 100 和 版本号为 0 的基础上的,所以事务二不会提交成功,应该重新读取金额和版本号,再次进行写操作。

这样,就避免了女柜员 用基于 = 0 的旧数据修改的结果覆盖男操作员操作结果的可能。

CAS 算法

省略代码,完整代码请参照 看完你就应该能明白的悲观锁和乐观锁

CAS 即 and swap(比较与交换)java replace [,是一种有名的无锁算法。即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-

Java 从 JDK1.5 开始支持,java.util. 包里提供了很多面向并发编程的类,也提供了 CAS 算法的支持,一些以 为开头的一些原子类都使用 CAS 作为其实现方式。使用这些类在多核 CPU 的机器上会有比较好的性能。

如果要保证它们的原子性,必须进行加锁,使用 或者 ,我们前面介绍它们是悲观锁的实现,我们现在讨论的是乐观锁,那么用哪种方式保证它们的原子性呢?请继续往下看

CAS 中涉及三个要素:

当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

我们以 java.util. 中的 为例,看一下在不用锁的情况下是如何保证线程安全的

public class AtomicCounter {

private AtomicInteger integer = new AtomicInteger;

public AtomicInteger getInteger {
return integer;
}

public voidsetInteger(AtomicInteger integer) {
this.integer = integer;
}

public voidincrement{
integer.incrementAndGet;
}

public voiddecrement{
integer.decrementAndGet;
}

}

public class AtomicProducer extendsThread{

private AtomicCounter atomicCounter;

publicAtomicProducer(AtomicCounter atomicCounter){
this.atomicCounter = atomicCounter;
}

@Override
public voidrun {
for(int j = 0; j < AtomicTest.LOOP; j++) {
System.out.println("producer : " + atomicCounter.getInteger);
atomicCounter.increment;
}
}
}

public class AtomicConsumer extendsThread{

private AtomicCounter atomicCounter;

publicAtomicConsumer(AtomicCounter atomicCounter){
this.atomicCounter = atomicCounter;
}

@Override
public voidrun {
for(int j = 0; j < AtomicTest.LOOP; j++) {
System.out.println("consumer : " + atomicCounter.getInteger);
atomicCounter.decrement;
}
}
}

public class AtomicTest {

final static int LOOP = 10000;

public static void main(String[] args) throws InterruptedException {

AtomicCounter counter = new AtomicCounter;
AtomicProducer producer = new AtomicProducer(counter);
AtomicConsumer consumer = new AtomicConsumer(counter);

producer.start;
consumer.start;

producer.join;
consumer.join;

System.out.println(counter.getInteger);

}
}

公告:
1. 本站所有资源来源于用户上传和网络,如有侵权请联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系站长处理!
6. 本站不售卖代码,资源标价只是站长收集整理的辛苦费!如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
7. 站长QQ号码 2205675299

资源库 - 资源分享下载网 » java replace [ 一文足以了解什么是 Java 中的锁

常见问题FAQ

关于资源售价和售后服务的说明?
本站所有资源的标价均为本站收集资源的辛苦费,不代表资源本身的价值。软件是高智慧高价值的商品,不可能是白菜价。本站资源标价只是赞助费用,收取的赞助费仅用来维持本站的日常运营!毕竟收集整理资料需要投入云计算资源和站长大量的精力。
代码有没有售后服务和技术支持?
由于代码的运行具有不可预见性,本站不保证代码完整可运行,不提供技术支持和售后服务。 本站原创代码都是站长自己开发的,可以有偿提供技术支持服务。 网站里标明【亲测】的代码都是站长亲测过的,其他的代码由于精力有限,没有一一测试,不能保证代码就一定能够使用,更没有技术支持服务,下载前请自行斟酌。
有没有搭建服务?
由于搭建服务比较费时费力,所以本站除了原创代码外均不提供搭建服务。本站分享代码纯属兴趣爱好,不以盈利为目的,请勿咨询有没有搭建服务,谢谢理解。
链接地址失效了怎么办?
请带上资源链接地址联系客服,工作时间内我们看到后将第一时间回复。
关于解压密码
本站资源一般都没有加密,如果发现需要解压密码的,那么就输入 hao.35dc.com 试试。

发表评论

资源库,由老程序员细心甄别、精心筛选,只为提供优质的源码资源

关于我们 联系我们