乐观锁和悲观锁

悲观锁:

总是假设最坏的情况:每次去拿数据的时候,都认为值会被别人修改。因此给值加上锁,这样别的线程就不能访问了。如synchronized和ReentrantLock就是悲观锁。适用于多写情形。

乐观锁:

总是假设最好的情况:每次去拿数据的时候,都认为值不会被别人修改。因此不会给值加锁。但是在更新的时候,会去判断这个数据是否被更新过。可以使用版本号机制和CAS算法实现。乐观锁适用于多读情形,这样可以提高吞吐量。

乐观锁的实现方式:

1.版本号机制:

一般在数据表加一个数据版本号(version),表示被修改的次数。每修改一次就+1一次。当线程A要修改数据时,在读取数据的同时也会读取version的值,之后将读出来的version和当前数据库中的version进行对比,相等才能更新。不然,重试更新操作,直到更新成功。

2.CAS算法:

CAS是一种有名的无锁算法,CAS有三个操作数,旧的预期值A,当前内存值V,要修改的新值B。当A=V时,说明值没有被修改过(忽略CAS的“ABA”问题),那么可以将新B赋给V,否则什么也不做。一般情况下是一个自旋操作,即不断重试。

乐观锁的缺点:

1CAS的“ABA”问题。

2.自旋CAS,不成功就会一直循环执行,直到成功。如果长时间不成功,会给CPU带来非常大的执行开销。

3.CAS只对单个共享变量有效,当操作涉及多个共享变量时,无效。

2.run()和start()的区别:

1.调用start()方法才是真正启动多线程,而且无需等待run方法体代码运行完毕,就可以直接运行后面的代码。

2.run()方法当做普通方法来调用,程序还是要按顺序执行,要等run方法体代码运行完毕,才能执行下面的代码。

如果直接调用run()方法,这也只是调用一个方法而已,程序中依然只有主线程这一个线程,程序也依然只有一条执行路径,那么也就失去了开辟线程的意义了。

3.多线程断点续传原理:

在本地下载过程中要使用数据库实时存储,到底存储到文件的哪个位置了。这样点击开始继续传递时,才能通过Http的GET请求中的setRequestProperty("Range","bytes=startIndex-endIndex")方法,告诉服务器,数据从哪里开始,到哪里结束。同时在本地的文件写入时,RandomAccessFile的seek()方法也支持在文件的任意位置进行写入操作。同时通过广播或事件总线机制将子线程的进度告知Activity的进度条。关于断点续传的HTTP状态码是206。

 

参考文章:https://juejin.im/post/5e5c5c52f265da575f4e7558#heading-134

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值