Android中多进程多线程模型学习(二)

53 篇文章 0 订阅
50 篇文章 0 订阅

上篇中学习了多进程和多线程的概念,该篇总结下多线程编程中的一些概念和遇到的问题。

一,线程安全,同步

1,锁

1.1基本概念

锁的分类:偏向锁、轻量级锁、重量级锁

锁升级:根据线程竞争锁的激烈程度,锁会从偏向锁升级为重量级锁

1.2 jvm对锁的优化

jvm内置锁存在的基本问题:线程切换的成本大,主要表现为:内核态和用户态的切换,线程切换

为了换取性能,JVM在内置锁上做了非常多的优化,膨胀式的锁分配策略就是其一

1.3 什么是CAS操作

常被用来解决独占锁对线程阻塞而导致的性能低下问题,是高效并发必备的一种优化方法。

CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试

CAS原理:基本原理是比较和替换:内存值 预期值 更新值, 一个进程在修改一个变量时,通过对比内存值和预期值,如果相等,才会将更新值替换到内存。底层使用了unsafe调用底层实现。

1.4 ReenTrantLock可重入锁(和synchronized的区别)总结

2.线程安全的类,如何设计一个线程安全的类

3.不使用同步关键字,如何实现一个线程安全的单例?

3.1

//不使用同步关键字实现一个线程安全的单例
public class Singleton {
    //1.私有构造函数
    private Singleton() {
    }

    //静态内部类,该模式使用了懒加载,类虽然加载了,但是实例没有被初始化
    private static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }

    //公有的方法供外部使用
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
    //总结:实现原理都是利用借助了类加载的时候初始化单例。即借助了ClassLoader的线程安全机制

}

3.2使用CAS机制

//不使用同步关键字实现一个线程安全的单例,使用CAS机制
public class CASSingleton {
    //CAS变量
    private static final AtomicReference<CASSingleton> INSTANCE = new AtomicReference<CASSingleton>();

    //1.私有构造函数
    private CASSingleton() {
    }

    public static CASSingleton getInstance() {
        for (;;) {
            CASSingleton casSingleton = INSTANCE.get();
            if (null != casSingleton) {
                return casSingleton;
            }
            casSingleton = new CASSingleton();
            if (INSTANCE.compareAndSet(null, casSingleton)) {
                return casSingleton;
            }
        }
    }
}

用CAS的好处在于不需要使用传统的锁机制来保证线程安全,CAS是一种基于忙等待的算法,依赖底层硬件的实现,相对于锁它没有线程切换和阻塞的额外消耗,可以支持较大的并行度。CAS的一个重要缺点在于如果忙等待一直执行不成功(一直在死循环中),会对CPU造成较大的执行开销。另外,如果N个线程同时执行到singleton = new Singleton();的时候,会有大量对象创建,很可能导致内存溢出。

4.容器

1.Reentrantlock

https://blog.csdn.net/u011521203/article/details/80186741

HashMap
1.hashmap的原理
2.hashmap三要素:hash 数组 链表
3.hashmap的长度,如何实现一个分布均匀的hash函数
index = HashCode(Key) & (hashMap.length - 1);
设计者使用 hashcode值与长度“与运算”,保证算出来的index位置均匀分布。因为(hashMap.length - 1)的二进制所有位数均为1
index的结果就等同于HashCode后几位的值。只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。这也是HashMap设计的玄妙之处。
4.HashMap扩容
5.HashMap冲突处理
6.HashMap的死锁
hashmap是非线程安全的,多线程下访问会造成死锁
https://coolshell.cn/articles/9606.html
总体介绍:参考:https://blog.csdn.net/mbshqqb/article/details/79799009
总结:
(1) 扩容是一个特别耗性能的操作,所以当程序员在使用HashMap的时候,估算map的大小,初始化的时候给一个大致的数值,避免map进行频繁的扩容。
(2) 负载因子是可以修改的,也可以大于1,但是建议不要轻易修改,除非情况非常特殊。
(3) HashMap是线程不安全的,不要在并发的环境中同时操作HashMap,建议使用ConcurrentHashMap。
(4) JDK1.8引入红黑树大程度优化了HashMap的性能。
HashTable
1.线程安全的,但是效率低
一,线程安全的容器

Hashtable-->ConcurrentHashMap
Vector-->CopyOnWriteArrayList/CopyOnWriteArraySet

总结:新的线程安全容器比之前老的线程安全的容器相比,锁的粒度小了,安全访问的同时提高了访问效率

ConcurrentHashMap的原理
1.线程安全的实现
2.读取效率高
3.相比HashTable,锁的粒度变小,以一个Segment为单位,如果线程A读取SegmentA,此时线程B是无法访问SegmentA的,但是可以访问其它Segment段

二,线程池

https://cloud.tencent.com/developer/article/1006754?ref=myread

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值