首页 / JAVA / Java并发之原子性
Java并发之原子性
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java并发之原子性,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2749字,纯文字阅读大概需要4分钟。
内容图文
![Java并发之原子性](/upload/InfoBanner/zyjiaocheng/609/77c460f6864343d382d28d9eae2ce244.jpg)
人生有涯,学海无涯
原子性定义:一个或者多个操作在 CPU 执行的过程中不被中断的特性。
一、出现原子性问题的原因
导致共享变量在线程之间出现原子性问题的原因是上下文切换。
那么接下来,我们通过一个例子来重现原子性问题。
package td;
import java.util.ArrayList;
import java.util.List;
/**
* 演示:原子性问题 -> 指当一个线程对共享变量操作到一半时,另外一个线程也有可能来操作共享变量,干扰了第一个线程的操作
*/
public class Test02Atomicity {
//定义一个共享变量
private static int number = 0;
public static void addNumber(){
number++;
}
public static void main(String[] args) throws InterruptedException {
//对number进行1000的++
Runnable runnable = () -> {
for (int i = 0; i < 1000; i++) {
addNumber();
}
};
List<Thread> list = new ArrayList<>();
//使用10个线程来进行操作
for (int i = 0; i < 10; i++) {
Thread t = new Thread(runnable);
t.start();
list.add(t);
}
for (Thread t : list) {
//t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程
t.join();
}
System.out.println("number = " + number);
}
}
多次运行上面的程序,也有我们期望的结果 number = 10000
,当时会出现不是我们想要的结果。
出现上面情况的原因就是因为
public static void addNumber(){
number++;
}
这段代码并不是原子操作,其中的number
是一个共享变量。在多线程环境下可能会被打断。就这样原子性问题就赤裸裸的出现了。
二、解决上下文切换带来的原子性问题
2.1、synchronized
synchronized既可以保证操作的可见性,也可以保证操作结果的原子性。
所以,此处我们只需要将addNumber()方法设置成synchronized的就能保证原子性了。
public synchronized static void addNumber(){
number++;
}
2.2、Lock锁
static Lock lock = new ReentrantLock();
public static void addNumber(){
lock.lock();//加锁
try{
number++;
}finally {
lock.unlock();//释放锁
}
}
Lock锁保证原子性的原理和synchronized类似
2.3、原子操作类型
JDK提供了很多原子操作类来保证操作的原子性。比如最常见的基本类型:
AtomicBoolean
AtomicLong
AtomicDouble
AtomicInteger
这些原子操作类的底层是使用CAS机制的,这个机制保证了整个赋值操作是原子的不能被打断的,从而保证了最终结果的正确性。
和synchronized相比,原子操作类型相当于是从微观上保证原子性,而synchronized是从宏观上保证原子性。
public class Test02Atomicity {
//定义一个共享变量
private static AtomicInteger number = new AtomicInteger();
public static void add(){
number.incrementAndGet();
}
public static int get(){
return number.get();
}
public static void main(String[] args) throws InterruptedException {
//对number进行1000的++
Runnable runnable = () -> {
for (int i = 0; i < 1000; i++) {
add();
}
};
List<Thread> list = new ArrayList<>();
//使用5个线程来进行操作
for (int i = 0; i < 10; i++) {
Thread t = new Thread(runnable);
t.start();
list.add(t);
}
for (Thread t : list) {
//t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。并不影响同一时刻处在运行状态的其他线程
t.join();
}
System.out.println("number = " + get());
}
}
内容总结
以上是互联网集市为您收集整理的Java并发之原子性全部内容,希望文章能够帮你解决Java并发之原子性所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。