静态变量、实例变量、局部变量、常量以及线程安全
静态变量也称为类变量,由static关键字修饰,在任何方法、构造函数或代码块外部。类变量在程序启动时被创建,在程序停止时被销毁。类变量被存储在静态存储器中。类变量通过类名访问。
常量,由final关键字修饰,静态变量的特性常量都有,除此之外,常量必须声明时就被赋值且不能再被改变。常量名一般大写。常量被存储在常量存储器内。
实例变量,声明在任意方法、构造函数或代码块外部。在对象“new”时被创建,对象销毁时被销毁。实例变量是对象的一部分,同对象一起存储在堆中。实例变量通过对象访问。
局部变量,在方法、构造函数或代码块中声明。局部变量在进入方法、构造函数或块时创建,退出时被销毁。局部变量存放在各自栈帧的工作内存中。
常量是线程安全的
常量一旦声明就禁止修改,所以是线程安全的。
静态变量(类变量)不是线程安全的
单例(非线程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private static int count; //声明静态变量 public void run() { count = 5; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"线程"+i).start(); } } }
本应输出的count全部为10,但是根据结果表明静态变量在单例模式下非线程安全
[线程21] 获取的count 值为 5 [线程53] 获取的count 值为 5 [线程270] 获取的count 值为 10 [线程37] 获取的count 值为 5 [线程341] 获取的count 值为 10 [线程306] 获取的count 值为 10 [线程126] 获取的count 值为 5 [线程30] 获取的count 值为 5 [线程125] 获取的count 值为 5 [线程117] 获取的count 值为 5 [线程46] 获取的count 值为 5 [线程118] 获取的count 值为 5 [线程110] 获取的count 值为 5 [线程109] 获取的count 值为 5 [线程94] 获取的count 值为 5
更改代码将ts 更换成 new ThreadSafety()
非单例(非线程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private static int count; //声明静态变量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"线程"+i).start(); } } }
根据结果发现,静态变量在非单例模式下也非线程安全
[线程62] 获取的count 值为 10 [线程118] 获取的count 值为 10 [线程122] 获取的count 值为 10 [线程123] 获取的count 值为 5 [线程121] 获取的count 值为 10 [线程126] 获取的count 值为 10 [线程133] 获取的count 值为 10 [线程119] 获取的count 值为 5 [线程124] 获取的count 值为 10 [线程120] 获取的count 值为 10 [线程95] 获取的count 值为 10
实例变量 单例模式下是非线程安全的,非单例模式下是线程安全的。
单例模式
import org.junit.Test; public class ThreadSafety implements Runnable{ private int count; //声明实例变量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"线程"+i).start(); } } }
[线程14] 获取的count 值为 10 [线程27] 获取的count 值为 10 [线程6] 获取的count 值为 10 [线程11] 获取的count 值为 10 [线程16] 获取的count 值为 10 [线程26] 获取的count 值为 10 [线程21] 获取的count 值为 10 [线程23] 获取的count 值为 5 [线程5] 获取的count 值为 5 [线程4] 获取的count 值为 10 [线程3] 获取的count 值为 5 [线程35] 获取的count 值为 10 [线程42] 获取的count 值为 10 [线程7] 获取的count 值为 10 [线程0] 获取的count 值为 10
非单例模式(线程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ private int count; //声明实例变量 public void run() { count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"线程"+i).start(); } } }
局部变量(线程安全)
单例(线程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ public void run() { int count; //声明局部变量 count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(ts,"线程"+i).start(); } } }
非单例(线程安全)
import org.junit.Test; public class ThreadSafety implements Runnable{ public void run() { int count; //声明局部变量 count = 5; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } count = 10; System.out.println("[" +Thread.currentThread().getName()+"] 获取的count 值为 "+count ); } @Test public void test(){ // ThreadSafety ts = new ThreadSafety(); for (int i=0;i<1000;i++){ new Thread(new ThreadSafety(),"线程"+i).start(); } } }