版权声明:如需转载,请标明转载出处哦! https://blog.csdn.net/Z0157/article/details/81489930
volatile: 使变量在多个线程间可见
(1)、在java中每一个线程都会有一块工作内存,其中存放着是所有线程共享的主内存的变量值的拷贝。
(2)、当前线程执行时,他在自己的工作内存区操作这些变量。
(3)、为了存取一个共享的变量,一个线程通常是先获取锁定并清除他的内存工作区,把共享变量从
所有的线程的共享内存中正确装入到他自己的工作内存区域中。
(4)、当线程解锁的时候保证该工作区的变量的值写回到共享内存中。
作用:volatile的作用是强制线程到主内存(共享内存)里去读取变量,而不是去工作内存区里去读取,
从而实现了多个线程间的变量可见,也是满足线程安全的可见性。
1、volatile关键字虽然拥有读个线程之间的可见性,但是却不具备同步性(也就是原子性);
2、volatile相当于一个轻量级的synchronized,性能比synchronized 强很多,不会造成阻塞,
像netty中大量使用volatile,但是他并不能待敌synchronized的同步功能,只是针对多个
线程可见的变量操作。
3、原子性操作可以使用atomic类的系列对象(只能保证本身方法原子性,并不能保证多次操作的原子性)
eg: num.addAndGet(1);
num.addAndGet(1);
连续操作了多次,是无法保证原子性的;
测试代码:
import java.util.concurrent.atomic.AtomicInteger;
/**
* volatile关键字不具备synchronized关键字的原子性(同步)
*
*/
public class VolatileNoAtomic extends Thread{
//private static volatile int count;
private static AtomicInteger count = new AtomicInteger(0);
private static void addCount(){
for (int i = 0; i < 1000; i++) {
//count++ ;
count.incrementAndGet();
}
System.out.println(count);
}
public void run(){
addCount();
}
public static void main(String[] args) {
VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
for (int i = 0; i < 10; i++) {
arr[i] = new VolatileNoAtomic();
}
for (int i = 0; i < 10; i++) {
arr[i].start();
}
}
}
public class RunThread extends Thread{
private volatile boolean isRunning = true;
private void setRunning(boolean isRunning){
this.isRunning = isRunning;
}
public void run(){
System.out.println("进入run方法..");
int i = 0;
while(isRunning == true){
//..
}
System.out.println("线程停止");
}
public static void main(String[] args) throws InterruptedException {
RunThread rt = new RunThread();
rt.start();
Thread.sleep(1000);
rt.setRunning(false);
System.out.println("isRunning的值已经被设置了false");
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicUse {
private static AtomicInteger count = new AtomicInteger(0);
//多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
/**synchronized*/
public synchronized int multiAdd(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
count.addAndGet(1);
count.addAndGet(2);
count.addAndGet(3);
count.addAndGet(4); //+10
return count.get();
}
public static void main(String[] args) {
final AtomicUse au = new AtomicUse();
List<Thread> ts = new ArrayList<Thread>();
for (int i = 0; i < 100; i++) {
ts.add(new Thread(new Runnable() {
@Override
public void run() {
System.out.println(au.multiAdd());
}
}));
}
for(Thread t : ts){
t.start();
}
}
}
测试结果我就不贴出来,希望阅读的人自己动手去写,写完了,运行了,对volatile使用也就彻底了解了;