静态变量也称为类变量,由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();
}
}
}