并发编程:并发集合:变量句柄(VarHandle)

目录

VarHandle

一、主程序

二、属性类

三、对属性进行加法操作

四、对属性进行减法操作

五、执行结果


VarHandle

Java9的新特性,它允许获得一个类型参考,以在不同的模式中访问一个变量(实例字段、静态字段或数组元素)。

在Java9之前,只能获得原子性变量的行为,现在,可以使用变量句柄来获得相同的功能而不用任何同步机制。(即,你可以操作普通变量时,使其原子性的变化。)

一、主程序

程序分別对Account的2个属性进行了10000次的加法和减法。线程安全的操作结果一定为0.非安全的操作可能不为零。

package xyz.jangle.thread.test.n7_XI.varhandle;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;

/**
 * 7.11、变量句柄 VarHandle 程序分別对Account的2个属性进行了10000次的加法和减法。
 * 线程安全的操作结果一定为0.非安全的操作可能不为零。
 * 
 * @author jangle
 * @email [email protected]
 * @time 2020年9月19日 下午5:59:42
 * 
 */
public class M {

	public static void main(String[] args) {

		Account account = new Account();
		var inc = new Thread(new Incrementer(account));
		var dec = new Thread(new Decrementer(account));
		inc.start();
		dec.start();
		try {
			inc.join();
			dec.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("安全的属性操作:" + account.amount);
		System.out.println("非安全的属性操作:" + account.unsafeAmount);

		try {
			VarHandle handle = MethodHandles.lookup().in(Account.class).findVarHandle(Account.class, "amount",
					double.class);
			// 读取变量,如同该值声明了volatile
			var amount = handle.getVolatile(account);
			// 读取变量,如同该值未声明volatile
			var amount2 = handle.get(account);
			// 读取变量,保证指令优化之前,后续的修改或访问该变量的指令不会被重排序
			var amount3 = handle.getAcquire(account);
			// 读取变量,保证当前线程中的指令不会重排序,但不保证其他线程。
			var amount4 = handle.getOpaque(account);
			System.out.println(amount + "," + amount2 + "," + amount3 + "," + amount4);
			VarHandle handle2 = MethodHandles.lookup().in(Account.class).findVarHandle(Account.class, "unsafeAmount",
					double.class);
			var unsafeAmount = handle2.get(account);
			System.out.println(unsafeAmount);
			// 设置变量,如同该值未声明volatile
			handle2.set(account,999);
			System.out.println(handle2.get(account));
			// 设置变量,如同该值声明了volatile
			handle2.setVolatile(account,777);
			System.out.println(handle2.getVolatile(account));
			// 设置变量,保证指令优化之前,后续的修改或访问该变量的指令不会被重排序
			handle2.setRelease(account,666);
			System.out.println(handle2.getAcquire(account));
			// 设置变量,保证当前线程中的指令不会重排序,但不保证其他线程。
			handle2.setOpaque(account,555);
			System.out.println(handle2.getOpaque(account));
//			handle2.weakCompareAndSet(account,555.0,333);
//			handle2.compareAndSet(account,555.0,333);
//			System.out.println(handle2.get(account));
		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

	}

}

二、属性类

package xyz.jangle.thread.test.n7_XI.varhandle;

/**
 * 属性类
 * @author jangle
 * @email [email protected]
 * @time 2020年9月19日 下午6:03:08
 * 
 */
public class Account {

	public double amount;
	public double unsafeAmount;

	public Account() {
		super();
		this.amount = 0;
		this.unsafeAmount = 0;
	}

}

三、对属性进行加法操作

package xyz.jangle.thread.test.n7_XI.varhandle;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;

/**
 * 对变量进行加法操作
 * 
 * @author jangle
 * @email [email protected]
 * @time 2020年9月19日 下午6:09:33
 * 
 */
public class Incrementer implements Runnable {

	private Account account;

	public Incrementer(Account account) {
		super();
		this.account = account;
	}

	@Override
	public void run() {
		VarHandle handler;
		try {
			for (int i = 0; i < 10000; i++) {
				handler = MethodHandles.lookup().in(Account.class).findVarHandle(Account.class, "amount", double.class);
				handler.getAndAdd(account, 100);
				account.unsafeAmount += 100;
			}
		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

	}

}

四、对属性进行减法操作

package xyz.jangle.thread.test.n7_XI.varhandle;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;

/**
 * 对变量进行减法操作
 * 
 * @author jangle
 * @email [email protected]
 * @time 2020年9月19日 下午6:04:30
 * 
 */
public class Decrementer implements Runnable {

	private Account account;

	public Decrementer(Account account) {
		super();
		this.account = account;
	}

	@Override
	public void run() {
		VarHandle handler;
		try {
			handler = MethodHandles.lookup().in(Account.class).findVarHandle(Account.class, "amount", double.class);
			for (int i = 0; i < 10000; i++) {
				handler.getAndAdd(account, -100);
				account.unsafeAmount -= 100;
			}
		} catch (NoSuchFieldException | IllegalAccessException e) {
			e.printStackTrace();
		}

	}

}

五、执行结果

安全的属性操作:0.0
非安全的属性操作:-200.0
0.0,0.0,0.0,0.0
-200.0
999.0
777.0
666.0
555.0

 

你可能感兴趣的:(并发编程,#,JavaBase,#,并发集合,java,反射,并发编程)