前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java并发编程(四)

java并发编程(四)

作者头像
疯狂的KK
发布2020-03-11 10:28:22
2710
发布2020-03-11 10:28:22
举报
文章被收录于专栏:Java项目实战Java项目实战

根据课程大纲整理资料。

21:volatile关键字的可见性

volatile 解决的是多核CPU带来的缓存与CPU之间数据的可见性,实现禁止指令重排

volatile即内存屏障,可保证一段内存中一个变量的原子性,原生类型都是原子性的。所以java中 volatile long,volatile double都是线程安全的。

22:volatile与static的关系

volatile 是保证从主内存加载到线程工作内存的值是最新的,此时并未加载并刷新到主内存中,static表示当前类的实例在主内存中用的是同一份。只能保证变量的来源,volatile, 声明变量值的一致性;static,声明变量的唯一性。

23:Atomic的原子性

原生类型都是原子性,以AtomicInteger为例

代码语言:javascript
复制
{@link java.util.concurrent.atomic} package specification for
 * description of the properties of atomic variables

getAndIncrement()方法会原子性的进行增量操作把当前值加1。Atomic要跟CAS放在一起

代码语言:javascript
复制
public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

24:CAS Compare and Swap

代码语言:javascript
复制
private static final Unsafe unsafe

private volatile int value;

unsafe类是CAS的核心类,是由C语言native方法来访问的

代码语言:javascript
复制
public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

其中getAndAddInt方法,this表示当前对象valueoffset表示内存中的偏移地址,delta是当前value增加的变量

CAS即比较当前值与预设值,交换并增加,如果与预想一致就交换,否则再次自旋,所以带来循环开销问题,进而引来ABA问题。

25:Threadlocal

这个类提供线程局部变量。 这些变量与其正常的对应方式不同,因为访问一个的每个线程(通过其getset方法)都有自己独立初始化的变量副本。 ThreadLocal实例通常是希望将状态与线程关联的类中的私有静态字段(例如,用户ID或事务ID)

1.如果多个线程访问同一个共享Threadlocal变量,是保证线程隔离的,A,B,C访问的即Threadlocal的变量副本

2.与线程状态相关,单个线程内,该线程持有该资源变量是私有的

Threadlocal并不是为了保证线程安全,而是为了在线程内方便共享变量跨方法的传递

经典用法:@Transactional事务的处理,利用其get方法获取Entry[],为每一个线程提供变量的副本,实现线程的隔离,每个线程只访问自己的数据。

26:InheritableThreadLocal与Threadlocal

首先InheritableThreadLocal继承了Threadlocal,Inheritable本身即是继承的意思,

代码语言:javascript
复制
/**
 * This class extends <tt>ThreadLocal</tt> to provide inheritance of values
 * from parent thread to child thread: when a child thread is created, the
 * child receives initial values for all inheritable thread-local variables
 * for which the parent has values.  Normally the child's values will be
 * identical to the parent's; however, the child's value can be made an
 * arbitrary function of the parent's by overriding the <tt>childValue</tt>
 * method in this class.
 *
 * <p>Inheritable thread-local variables are used in preference to
 * ordinary thread-local variables when the per-thread-attribute being
 * maintained in the variable (e.g., User ID, Transaction ID) must be
 * automatically transmitted to any child threads that are created.
 *
 * @author  Josh Bloch and Doug Lea
 * @see     ThreadLocal
 * @since   1.2
 */

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
          ...
}

创建子线程时,子线程接收所有可继承线程局部变量的初始值。

说实话第一次听到跟他比较,比如ThreadLocal VS FastThreadlocal,既然是继承,大多是为了扩展父类方法,解决其threadlocal.get()得不到其新线程中的值,

代码语言:javascript
复制
推荐博客:
https://blog.csdn.net/ni357103403/article/details/51970748

27:Unsafe类详解

Unsafe类除了CAS理解相关以外,确实了解的不多,这里推荐美团技术博客

代码语言:javascript
复制
Java魔法类:Unsafe应用解析
https://tech.meituan.com/2019/02/14/talk-about-java-magic-class-unsafe.html

它属于native.C语言编写的类,在cas,netty中都有应用。这里提到了线程调度可用于线程挂起,真实调用了park()方法实现。

28:同步类容容器

CopyOnWriteArraySet

ConcurentSkipListSet

ConcurrentHashMap

与 ConcurrentSkipListMap

ConcurrentHashMap 加锁

ConcurrentSkipListMap 不需要加锁,浪费空间

29:ConcurrentHashMap

Hashmap是并发线程不安全的,其无法解决共享变量的安全问题,那么解决的方法为

1.替换为Hashtable

2.Collections.synchronizedMap()

3.ConcurrentHashMap

其中Hashtable之所以安全因为其put,get等大多数方法为synchronized

修饰的,但并发场景下锁的粒度太重,性能降低

Collections.synchronizedMap()

代码语言:javascript
复制
public static void main(String[] args) {
   HashMap<String, String> map = new HashMap<>();
   Map<String, String> synchronizedMap = Collections.synchronizedMap(map);
}

其put方法get方法也都是synchronized

代码语言:javascript
复制
 public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
 }
  public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
 }

ConcurrentHashMap

1.7是锁分段 segment 16,隔离级别太大,有很多空间就浪费了,太小就段内的元素过多

1.8以后是cas算法C语言写得,无锁算法,put添加的时候,链表+红黑树

put方法(无锁添加)

29:无阻塞队列ConcurrentLinkedQueue

代码语言:javascript
复制
An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
 * This queue orders elements FIFO (first-in-first-out).
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
        implements Queue<E>, java.io.Serializable {
        
}

一个为绑定线程安全的队列,队列的元素先进先出

看其节点的内部方法

代码语言:javascript
复制
 /**
  * Constructs a new node.  Uses relaxed write because item can
  * only be seen after publication via casNext.
 */
 Node(E item) {
            UNSAFE.putObject(this, itemOffset, item);
        }
构造新节点。使用轻松写入,因为item可以仅在通过casNext发布后才能看到

那其实还是跟Unsafe类离不开。

代码语言:javascript
复制
推荐博客http://ifeve.com/concurrentlinkedqueue/
代码语言:javascript
复制
我没有梦见你,
但我梦见了糖葫芦,
醒来我突然觉得我好久没吃过糖葫芦了
然后就想跟你讲一下
可能
你和糖葫芦一样甜吧
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 赵KK日常技术记录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档