《学习多线程03》关键字volatile
程序员文章站
2022-03-08 20:18:10
...
volatile的基础知识
1.可见性,保证不同线程操作该变量的可见性,即一个线程修改该变量,这个新的值对其他线程来说是立刻知道的
2.禁止进行指令重排序(虚拟机层面,有自己的规则,对代码进行排序),有序性
3.volatile只能保证单次读/写的原子性。i++这种不能保证
简单实战
1.volatile定义的值改变,其他线程能否查看(可见性)
public class VolatileTestOne {
private volatile int n = 0;
public static void main(String[] args) {
volatileTest();
}
//单次读写保证原子性
public void addNumber(){
n++;
}
public static void volatileTest(){
VolatileTestOne volatileTestOne = new VolatileTestOne();
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.execute(()->{
System.out.println("one");
for (int i=0;i<10;i++){
volatileTestOne.addNumber();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("oneOver");
});
executorService.execute(()->{
System.out.println("two");
for (int i=0;i<10;i++){
System.out.println(volatileTestOne.n);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("twoOver");
});
executorService.shutdown();
while (!executorService.isTerminated()){
}
System.out.println(" "+volatileTestOne.n);
}
}
执行结果
2.进行自增操作,不能确保原子性。
public class VolatileTestTwo {
private volatile int n = 0;
public static void main(String[] args) {
volatileTest();
}
public static void volatileTest() {
VolatileTestTwo volatileTestTwo = new VolatileTestTwo();
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int j=0;j<5;j++){
executorService.execute(() -> {
for (int i=0; i < 1000; i++) {
volatileTestTwo.n++;
}
});
}
executorService.shutdown();
while (!executorService.isTerminated()){
}
System.out.println(" "+volatileTestTwo.n);
}
}
执行结果
多次执行我们会发现还会有其他的结果
不能确保原子性
3.如何解决自增并保证原子性?
public class VolatileTestThree {
private volatile int n = 0;
Lock lock = new ReentrantLock();
public static void main(String[] args) {
volatileTest();
}
//法(1)进行synchronized加锁
// public synchronized void addNumber(){
// n++;
// }
//法(2)进行lock加锁
public void addNumber(){
lock.lock();
try {
n++;
}finally {
lock.unlock();
}
}
public static void volatileTest() {
VolatileTestThree volatileTestThree = new VolatileTestThree();
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int j=0;j<10;j++){
executorService.execute(() -> {
for (int i=0; i < 1000; i++) {
volatileTestThree.addNumber();
}
});
}
executorService.shutdown();
while (!executorService.isTerminated()){
}
System.out.println(" "+volatileTestThree.n);
}
}
执行结果
加锁后不管怎么执行,都会正确。
文章我会持续坚持更新,若有问题可以直接联系我,文章会同步到公众号上!微信搜索【雨季的代码人生】或直接扫码关注,回复“问题”即可。
上一篇: Java线程的几种状态
下一篇: AI简单绘制一个不规则的折线