Java中static和volatile的区别

本文详细解释了Java中的transient和volatile关键字的用法和区别,包括序列化过程中的应用、static和volatile的特性对比以及通过实例演示它们在多线程环境中的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天去面试,把transient当成volatile说了,很是丢脸,今天在这里记录一下。

1. 首先说一下什么是transient。

1) transient keyword is used along with instance variables to exclude them from serialization process. if a field  is transient its value will not be persisted. see my post what is transient keyword in java for more details. On the other hand volatile keyword can also be used in variables to indicate compiler and JVM that always read its value from main memory and follow happens-before relationship on visibility of volatile variable among multiple thread. see my post how and when to use volatile keyword in Java for more details.
 transient就是在序列化时,标记变量,不用被序列化。

2) transient keyword can not be used along with static keyword but volatile can be used along with static.

 语义上来说,transient是可以被static修饰的,但是没有什么实际意义。
3) transient variables are initialized with default value during de-serialization and there assignment or restoration of value has to be handled by application code.
在反序列化时,transient变量会被初始化成初始值,应用程序自己需要自己在处理它们的值。

Read more: http://javarevisited.blogspot.com/2012/03/difference-between-transient-and.html#ixzz2siNRg1eC

2. 啰嗦完毕,言归正传,那么static和volatile的区别是什么呢?

static是Object之间共享的变量;static变量可能会被线程cache;static可以修饰volatile
volatile是线程之间共享的变量;

http://malalanayake.wordpress.com/2013/09/12/volatile-vs-static-in-java/

http://javarevisited.blogspot.de/2011/06/volatile-keyword-java-example-tutorial.html


例子一:

public class VolatileExample {
	public static void main(String args[]) {
		new ExampleThread("Thread 1 ").start();
		new ExampleThread("Thread 2 ").start();
	}
}

class ExampleThread extends Thread {
	private static double testValue = 1;
	private static boolean isExit = false;

	public ExampleThread(String str) {
		super(str);
	}

	@Override
	public void run() {
		if (getName().compareTo("Thread 2 ") == 0) {
			while (true) {
				System.out.println(getName() + "Test Value T2: " + testValue);

				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				if (isExit) {
					return;
				}
			}
		}
			
		
		for (int i = 0; i < 10; i++) {
			try {
				if (getName().compareTo("Thread 1 ") == 0) {
					testValue++;
					System.out.println(getName() + "Test Value T1: " + testValue);
					
					Thread.sleep(100);
					
					if(i == 9) {
						isExit = true;
					}
				}				
				
			} catch (InterruptedException exception) {
				exception.printStackTrace();
			}
		}		
	}
}


上面的代码运行结果是:

Thread 2 Test Value T2: 2.0
Thread 1 Test Value T1: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 2 Test Value T2: 2.0
Thread 1 Test Value T1: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 2 Test Value T2: 3.0
Thread 1 Test Value T1: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 2 Test Value T2: 4.0
Thread 1 Test Value T1: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 2 Test Value T2: 5.0
Thread 1 Test Value T1: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 2 Test Value T2: 6.0
Thread 1 Test Value T1: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 2 Test Value T2: 7.0
Thread 1 Test Value T1: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 2 Test Value T2: 8.0
Thread 1 Test Value T1: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 2 Test Value T2: 9.0
Thread 1 Test Value T1: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 2 Test Value T2: 10.0
Thread 1 Test Value T1: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0
Thread 2 Test Value T2: 11.0

从这里可以看到,static变量在不通的线程之间是可以共享的,这好像和上面说的不一样?

每次线程1改变testValue之后,线程2都能取道改变后的值。

其实例子的输出和CPU和JVM的版本都有关系,JVM不保证变量在不同的线程之间是可见的,只有线程之间建立了happen-before关系。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值