身为JAVA工作者必须了解的实战知识(十四)

一、锁的劣势

锁定后如果未释放,再次请求锁时会造成阻塞,多线程调度通常遇到阻塞会进行上下文切换,造成更多的开销。

在挂起与恢复线程等过程中存在着很大的开销,并且通常存在着较长时间的中断。

锁可能导致优先级反转,即使较高优先级的线程可以抢先执行,但仍然需要等待锁被释放,从而导致它的优先级会降至低优先级线程的级别。

二、硬件对并发的支持

处理器填写了一些特殊指令,例如:比较并交换、关联加载/条件存储。

1 比较并交换

CAS的含义是:“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不需要修改告诉V的值实际为多少”。CAS是一项乐观锁技术。

模拟CAS操作例子:

[java]view plaincopy

print?

@ ThreadSafe

publicclassSimulatedCAS {

@ GuardeBy("this")privateintvalue ;

publicsynchronizedintget(){

returnvalue ;

}

publicsynchronizedintcompareAndSwap(intexpectedValue,intnewValue){

intoldValue = value ;

if(oldValue == expectedValue)

value = newValue;

returnoldValue;

}

publicsynchronizedbooleancompareAndSet(intexpectedValue,intnewValue){

return(expectedValue == compareAndSwap(expectedValue, newValue));

}

}

2 非阻塞的计数器

基于CAS实现的非阻塞计数器

[java]view plaincopy

print?

@ ThreadSafe

publicclassCasCounter {

privateSimulatedCAS value ;

publicintgetValue(){

returnvalue .get();

}

publicintincrement(){

intv;

do{

v = value .get();

}while(v != value .compareAndSwap(v, v +1));

returnv +1;

}

}

CAS的主要缺点是:它将使调度者处理竞争问题(通过重试、回退、放弃),而在使用锁中能自动处理竞争问题(线程在获得锁之前将一直阻塞)。

3 JVM对CAS的支持

[java]view plaincopy

print?

java.util.concurrent.atomic 类的小工具包,支持在单个变量上解除锁的线程安全编程。

AtomicBoolean 可以用原子方式更新的boolean值。

AtomicInteger 可以用原子方式更新的int值。

AtomicIntegerArray 可以用原子方式更新其元素的int数组。

AtomicIntegerFieldUpdater 基于反射的实用工具,可以对指定类的指定volatileint字段进行原子更新。

AtomicLong 可以用原子方式更新的long值。

AtomicLongArray 可以用原子方式更新其元素的long数组。

AtomicLongFieldUpdater 基于反射的实用工具,可以对指定类的指定volatilelong字段进行原子更新。

AtomicMarkableReference AtomicMarkableReference 维护带有标记位的对象引用,可以原子方式对其进行更新。

AtomicReference 可以用原子方式更新的对象引用。

AtomicReferenceArray 可以用原子方式更新其元素的对象引用数组。

AtomicReferenceFieldUpdater 基于反射的实用工具,可以对指定类的指定volatile字段进行原子更新。

AtomicStampedReference AtomicStampedReference 维护带有整数“标志”的对象引用,可以用原子方式对其进行更新。

三、原子变量类

1 原子变量是一种“更好的volatile”

通过CAS来维持包含多个变量的不变性条件例子:

[java]view plaincopy

print?

importjava.util.concurrent.atomic.AtomicReference;

publicclassCasNumberRange {

privatestaticclassIntPair{

finalintlower ;// 不变性条件: lower <= upper

finalintupper ;

publicIntPair(intlower,intupper) {

this.lower = lower;

this.upper = upper;

}

}

privatefinalAtomicReference values =

newAtomicReference(newIntPair(0,0));

publicintgetLower(){

returnvalues .get(). lower;

}

publicintgetUpper(){

returnvalues .get(). upper;

}

publicvoidsetLower(inti){

while(true){

IntPair oldv = values .get();

if(i > oldv.upper ){

thrownewIllegalArgumentException("Cant't set lower to "+ i +" > upper");

}

IntPair newv =newIntPair(i, oldv.upper );

if(values .compareAndSet(oldv, newv)){

return;

}

}

}

// 对setUpper采用类似的方法

}

2 性能比较:锁与原子变量

使用ReentrantLock、AtomicInteger、ThreadLocal比较,通常情况下效率排序是ThreadLocal > AtomicInteger > ReentrantLock。

四、非阻塞算法

1 非阻塞的栈

[java]view plaincopy

print?

importjava.util.concurrent.atomic.AtomicReference;

publicclassConcurrentStack {

privateAtomicReference> top =newAtomicReference>();

publicvoidpush(E item){

Node newHead =newNode(item);

Node oldHead;

do{

oldHead = top .get();

newHead. next = oldHead;

}while(!top .compareAndSet(oldHead, newHead));

}

publicE pop(){

Node oldHead;

Node newHead;

do{

oldHead = top .get();

if(oldHead ==null) {

returnnull;

}

newHead = oldHead. next ;

}while(!top .compareAndSet(oldHead, newHead));

returnoldHead.item ;

}

privatestaticclassNode{

publicfinalE item;

publicNode next ;

publicNode(E item){

this.item = item;

}

}

}

2 非阻塞的链表

CAS基本使用模式:在更新某个值时存在不确定性,以及在更新失败时重新尝试。

[java]view plaincopy

print?

importjava.util.concurrent.atomic.AtomicReference;

@ ThreadSafe

publicclassLinkedQueue {

privatestaticclassNode{

finalE item;

finalAtomicReference> next;

publicNode(E item, Node next){

this.item = item;

this.next =newAtomicReference>(next);

}

}

privatefinalNode dummy =newNode(null,null);

privatefinalAtomicReference> head =

newAtomicReference>(dummy);

privatefinalAtomicReference> tail =

newAtomicReference>(dummy);

publicbooleanput(E item){

Node newNode =newNode(item,null);

while(true){

Node curTail = tail.get();

Node tailNext = curTail.next.get();

if(curTail == tail.get()){

if(tailNext !=null){

// 队列处于中间状态,推进尾节点

tail.compareAndSet(curTail, tailNext);

}else{

// 处于稳定状态, 尝试插入新节点

if(curTail.next.compareAndSet(null, newNode)){

// 插入操作成功,尝试推进尾节点

tail.compareAndSet(curTail, tailNext);

returntrue;

}

}

}

}

}

}

3 原子的域更新器

原子的域更新器类表示有volatile域的一种基于反射的“视图”,从而能够在已有的volatile域上使用CAS

[java]view plaincopy

print?

privatestaticclassNode{

privatefinalE item;

privatevolatileNode next;

publicNode(E item){

this.item = item;

}

}

privatestaticAtomicReferenceFieldUpdater nextUpdater

= AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class,"next");

4 ABA问题

处理V的值首先由A变成B,再由B变成A的问题。

好了同学们,我能介绍的也都全部介绍完给你们了,如果下获得更多JAVA教学资源,可以选择来我们这里共同交流,群:240448376,很多大神在这里切磋学习,不懂可以直接问,晚上还有大牛免费直播教学。

注:加群要求

1、具有一定工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加,有些应届生和实习生也可以加。

2、在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加。

3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加。

4、觉得自己很牛B,一般需求都能搞定。但是所学的知识点没有系统化,很难在技术领域继续突破的可以加。

5.阿里Java高级大牛直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立自己的技术体系和技术认知!

PS:现在主要讲解的内容是(反射原理枚举原理与应用注解原理常用设计模式、正规表达式高级应用、JAVA操作Office原理详解JAVA图像处理技术,等多个知识点的详解和实战)

6.小号或者小白之类加群一律不给过,谢谢。

最后,每一位读到这里的网友,感谢你们能耐心地看完。觉得对你有帮助可以给个喜欢!希望在成为一名更优秀的Java程序员的道路上,我们可以一起学习、一起进步

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • Java8张图 11、字符串不变性 12、equals()方法、hashCode()方法的区别 13、...
    Miley_MOJIE阅读 3,629评论 0 11
  • 一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 publicclassUnsa...
    Martin说阅读 2,165评论 0 6
  • 并发测试大致分为两类:安全性测试(不发生任何错误的行为)和活跃性测试(某个良好的行为终究会发生)。 安全测试 - ...
    a_decb阅读 399评论 0 1
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,004评论 11 349
  • 时间和周遭在试图磨灭着我的理想主义与善良本性,还好我智商低,对一切察觉太晚无力反抗,只有保持本性的走下去。
    Athena000阅读 90评论 0 0