加入收藏 | 设为首页 | 会员中心 | 我要投稿 武汉站长网 (https://www.027zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Java多线程(5):CAS

发布时间:2022-11-03 14:30:53 所属栏目:PHP教程 来源:转载
导读: 马上注册,结交更多好友,享用更多功能php多线程,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册

x
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

马上注册,结交更多好友,享用更多功能php多线程,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x

您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~

在JDK1.5之前,Java的多线程都是靠synchronized来保证同步的,这会引起很多性能问题,例如死锁。但随着Java的不断完善,JNI(Java Native Interface)使得Java能越过JVM直接调用本地方法,例如CAS。

CAS是Compare And Swap(比较与交换)的缩写,它用于实现多线程同步的原子指令,允许算法执行读-修改-写操作,而无需担心其他线程同时修改变量。说人话,意思就是它的操作过程足够细微,以至于线程都奈何不了它。

所谓原子指令就是指不会被线程调度机制打断的操作指令,这种操作一旦开始,就一直运行到结束,中间不会有任何线程切换,即要么全部完成,要么全部中断。换一种说法,就是CAS可以保证Java运算实现我们想要的操作而无需担心会受到多线程的影响。

某种程度上,CAS可以用来取代synchronized的强制同步,提升性能。其实整个java.util.concurrent包都是建立在CAS之上的,尤其是Java中大多数锁的实现基类AbstractQueuedSynchronizer,更是以CAS为基础,提供了一系列的独占锁、共享锁、可重入锁、自旋锁、读写锁等多线程控制手段(这在后面会说)。就像图中那样:

2983171-20221027232510631-1331846365.png

2983171-20221027232510631-1331846365.png

Java对CAS的实现都在java.util.concurrent.atomic包下(java.util.concurrent也简称JUC,这是个简称。所以如果有面试官说想让你谈谈JUC相关的问题,不要一脸懵,否则会被立即淘汰)。以AtomicInteger为例,从源码可以看出CAS操作都是通过sun包下Unsafe类实现,而Unsafe类中的方法都是native方法,由本地实现,和操作系统、CPU都有关系。CAS有一个比较通用的实现模式:

1、首先声明(共享)变量为volatile

2、然后使用CAS的原子条件来更新

3、同时配合volatile的可见性来实现线程之间的同步

前面讲过,不用深究volatile关键字的用途,因为随着机器配置的豪华,其实这个关键字已经没啥用了,而且也可以看到,在CAS里面也有大量出现,JDK已经替你用好了,自己如果不太熟悉就不要用了。CAS相关类结构图是:

2983171-20221027232521164-2105896128.png

2983171-20221027232521164-2105896128.png

还是老规矩,用代码来举例:

/**

* 仅用AtomicInteger实现CAS

*

* @author 湘王

*/

public class AtomicIntegerTester1 {

// 使用AtomicInteger实现CAS,有没有volatile都不影响

public static volatile AtomicInteger atomicInteger = new AtomicInteger(0);

public static void main(String[] args) throws InterruptedException {

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i = 0; i20; i++) {

Runnable runnable = new Runnable() {

@Override

public void run() {

atomicInteger.getAndIncrement();

}

};

executor.submit(runnable);

}

// 为了观察效果休眠,但实际生产环境中肯定不允许

Thread.sleep(100);

executor.shutdown();

System.out.println(atomicInteger.get());

}

}

/**

* 用AtomicIntegerFieldUpdater实现CAS

*

* @author 湘王

*/

public class AtomicIntegerTester2 {

/*

* 使用AtomicIntegerFieldUpdater实现CAS,相关计算字段必须用volatile修饰,不然抛异常

* Caused by: java.lang.IllegalArgumentException: Must be volatile type

*

*/

public volatile int count = 0;

public static final AtomicIntegerFieldUpdaterAtomicIntegerTester2 lockUpdate = AtomicIntegerFieldUpdater.newUpdater(AtomicIntegerTester2.class, "count");

public int increase(int inc) {

return lockUpdate.addAndGet(this, inc);

}

public int get() {

return lockUpdate.get(this);

}

public static void main(String[] args) throws InterruptedException {

AtomicIntegerTester2 tester = new AtomicIntegerTester2();

ExecutorService executor = Executors.newFixedThreadPool(3);

for (int i = 0; i20; i++) {

Runnable runnable = new Runnable() {

@Override

public void run() {

tester.increase(1);

}

};

executor.submit(runnable);

}

// 为了观察效果休眠,但实际生产环境中肯定不允许

Thread.sleep(100);

executor.shutdown();

System.out.println(tester.get());

}

}

CAS的内容并不多,可以看看它的源码,还是比较有意思的。

感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~

(编辑:武汉站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!