Java多线程之volatile的非原子特性

407 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

接上篇文章,上篇说到了轻量级同步机制:volative 关键字的作用,及与 synchronized的比较,今天这篇文章继续说说volatile的非原子特性。

程序的原子性概念:

一个操作的过程是不可中断的,要么全部执行成功要么全部执行失败,有着“同生共死”的感觉。即使在多个线程一起执行的时候,一旦一个原子性的操作开始后,就不会受其他线程的干扰。

volatile 非原子特性

volatile 关键字增加了实例变量在多个 线程之间的可见性,但是不具备原子性.

package com.wkcto.volatilekw;

/**

* volatile 不是具备原子性

* Author: 老崔

*/

public class Test03 {

public static void main(String[] args) {

//在 main 线程中创建 10 个子线程

for (int i = 0; i < 100; i++) {

new MyThread().start();

}

}

static class MyThread extends Thread{

//volatile 关键仅仅是表示所有线程从主内存读取 count 变量的值

public static int count;

/* //这段代码运行后不是线程安全的,想要线程安全,需要使用 synchronized 进行同

步,如果使用 synchronized 同时,也就不需要 volatile 关键了

public static void addCount(){

for (int i = 0; i < 1000; i++) {

//count++不是原子操作

count++;

}

System.out.println(Thread.currentThread().getName() + " count=" + count);}*/

public synchronized static void addCount(){

for (int i = 0; i < 1000; i++) {

//count++不是原子操作

count++;

}

System.out.println(Thread.currentThread().getName() + " count=" + count);

}

@Override

public void run() {

addCount();

}

}

}

常用原子类进行自增自减操作

我们知道 i++操作不是原子操作, 除了使用 Synchronized 进行同步外,也可以使用 AtomicInteger/AtomicLong 原子类进行实现

package com.wkcto.volatilekw;

import java.util.concurrent.atomic.AtomicInteger;

/**

* 使用原子类进行自增

* Author: 老崔

*/

public class Test04 {

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

//在 main 线程中创建 10 个子线程

for (int i = 0; i < 1000; i++) {

new MyThread().start();
}

Thread.sleep(1000);

System.out.println( MyThread.count.get());

}

static class MyThread extends Thread{

//使用 AtomicInteger 对象

private static AtomicInteger count = new AtomicInteger();

public static void addCount(){

for (int i = 0; i < 10000; i++) {

//自增的后缀形式

count.getAndIncrement();

}

System.out.println(Thread.currentThread().getName() + " count=" + count.get());

}

@Override

public void run() {

addCount();

}

}

}