Java 中能创建 volatile 数组吗?
答
可以创建 volatile 数组,但是volatile只保证对数组的引用可见,而不是数组元素。 即如果是改变引用指向的数组,将受到volatile的保护;但是对多个线程同时改变数组里面的元素,volatile不能保证。
volatile 的作用
作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
实现 volatile 数组 的两种方式
- 使用AtomicIntegerArray 或 AtomicLongArray
AtomicIntegerArray类实现一个int数组,通过类的get()和set()方法可以使用volatile语义访问各个字段。 - 自定义实现,在每次字段写入后重写数组引用,比较麻烦(因为现在一次写入涉及两次写入)
volatile int[] arrays = {1,1,1,1,1}
代码示例
package com.yueny.study.jdk.volatilex;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author fengyang <deep_blue_yang@126.com>
* @date 2020/9/28 2:58 下午
* @title: VolatileArrays
* @projectName algorithm
* @description:
*/
public class VolatileArrays {
// 不保证原子性
static volatile int[] arrays = {1,1,1,1,1};
// 不保证原子性
static int x = 0;
// 不保证原子性
static volatile int y = 0;
// 保证原子性
static volatile AtomicInteger z = new AtomicInteger(0);
private static ExecutorService executorService = Executors.newFixedThreadPool(5);
/**
* 模拟并发线程
*
* @param args
*/
public static void main(String []args) {
System.out.println("模拟操作前:");
System.out.println(Arrays.toString(arrays));
System.out.println("X:" + x);
System.out.println("Y:" + y);
System.out.println("Z:" + z);
// 模拟 1000 个线程进行 arrays、x、y、z 的累加
for (int i=0;i<10000;i++){
executorService.submit(new ChangeNum());
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("模拟操作结束, 执行1000次,期望均为 1000。");
System.out.println(Arrays.toString(arrays));
System.out.println("X:" + x);
System.out.println("Y:" + y);
System.out.println("Z:" + z);
}
static class ChangeNum implements Runnable{
@Override
public void run() {
/*
* 数据全部各自加1
*/
arrays[0]=arrays[0]+1;
arrays[1]=arrays[1]+1;
arrays[2]=arrays[2]+1;
arrays[3]=arrays[3]+1;
arrays[4]=arrays[4]+1;
x=x+1;
y=y+1;
z.incrementAndGet();
}
}
}
结果
模拟操作前:
[1, 1, 1, 1, 1]
X:0
Y:0
Z:0
模拟操作结束, 执行1000次,期望均为 1000。
[9995, 9996, 9996, 9997, 9998]
X:9997
Y:9997
Z:10000
正文到此结束
热门推荐
广告是为了更好的提供数据服务