每天一个面试题:悲观锁、乐观锁,对比Hashtable和concurrentHashMap

开始全新的学习,沉淀才会有产出,一步一脚印!
面试题系列搞起来,这个专栏并非单纯的八股文,我会在技术的基础上,Debug解析,还会做一些实例的实现,实现一些简单的Demo,或者用于我做过的项目中去;
代码会同步在我的gitee中去,觉得不错的同学记得一键三连求关注,感谢:
链接: CasAndSync

12.11 忌收纳
混乱是自由,令人畏惧的自由

悲观锁、乐观锁

  • 悲观锁
  1. 核心代表:就是锁机制:Synchronized和Lock锁
  2. 核心思想:只有占有了锁,才可去操作资源,否则就阻塞等待
  3. 过程:就是 运行-阻塞-唤醒 ,涉及到了上下文切换,如果频繁切换,对性能影响大
  4. 细节:实际上,线程在获取锁时,如果锁已经被占用,都会做几次重试操作,减少阻塞机会
  • 乐观锁
  1. 核心代表:AtomicInteger,通过CAS保证原子性
  2. 核心思想:无需加锁,每次只有一个线程可以成功修改共享变量,其它失败的线程不需要停止,不断重试直至成功;
  3. 过程:不会阻塞,一直运行
  4. 细节:需要多核CPU支持吗,线程数不超过CPU数
public class TsetCasAndSync {

    //为了实现原子性,U的操作都是原子的
    static final Unsafe U = Unsafe.getUnsafe();
    //表示偏移量:对于Account类和balance属性
    static final long BALANCE = U.objectFieldOffset(Account.class, "balance");

 
    static class Account{
    //volatile 保证可见性
        volatile int balance = 10;
    }

上面是为了保证操作这个资源是可以访问其序列号/偏移量的

    public static void main(String[] args) {
        Account account = new Account();
        while(true){
            int o = account.balance;
            int n = o+5;
            //调用
            if (U.compareAndSetInt(account, BALANCE,o,n)){
                break;
            }
        }
        while(true){
            int o = account.balance;
            int n = o-5;
            //调用
            if (U.compareAndSetInt(account, BALANCE,o,n)){
                break;
            }
        }
    }

}

这个针对了当前情况(U.compareAndSetInt(account, BALANCE,o,n)
o:当前变量
n:操作之后的变量
account:我们操作的资源

如果我们线程A操作account,到 if (U.compareAndSetInt(account, BALANCE,o,n)){ break; },如果balance被修改,那么当前线程会对比 account和o是否相同,不同就重新在来;

public class TsetCasAndSync {

    public static void sync(Account account){
        new Thread(()->{
            synchronized (account) {
                int old = account.balance;
                int n = old - 5;
                account.balance = n;
            }
        }).start();

        new Thread(()->{
            synchronized (account){
                int old = account.balance;
                int n = old + 5;
                account.balance = n;
            }

        }).start();
    }
    static class Account{
        volatile int balance = 10;
    }

    public static void main(String[] args) {
        Account account = new Account();
			sync(account );
    }

}

锁机制,占用无法被修改

Hashtable和concurrentHashMap

  1. 都是线程安全的Map集合
  2. Hashtable并发度低,全局使用一把锁,同一时刻,只有一个线程可以操控它
  3. 1.8之前ConcurrentHashMap使用了Segment+数组+链表的结构,每个Segment对应一把锁,支持多线程操作
  4. 1.8之后ConcurrentHashMap将数组的每个头结点作为锁,如果多个线程访问的头结点不同,就不会冲突

总结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值