实例变量与局部变量的区别

/ 多线程 / 没有评论 / 338浏览

在日常开发中,我们会创建实例变量和局部变量来处理我们的需求。在非多线程环境中我们发现它们的区别不太大,无非就是作用域不同而已。但在多线程环境中可能会发生我们意想不到的结果。请看下面的事例。

局部变量在多线程环境中的测试

/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {
public void login(String username) {
try {
int role = 0;
if ("admin".equals(username)) {
role = 1;
System.out.println("管理用户登录");
Thread.sleep(1000);
} else {
role = 2;
System.out.println("普通用户登录");
}
System.out.println(String.format("uername: %s\trole: %s", username, role));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 管理用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestAdmin extends Thread {

private Userinfo userinfo;

public RequestAdmin(Userinfo userinfo) {
this.userinfo = userinfo;
}

@Override
public void run() {
userinfo.login("admin");
}
}
/**
* 普通用户请求
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:44
* @since 1.0.0
*/
public class RequestUser extends Thread {

private Userinfo userinfo;

public RequestUser(Userinfo userinfo) {
this.userinfo = userinfo;
}

@Override
public void run() {
userinfo.login("user");
}
}
/**
* 测试类
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:49
* @since 1.0.0
*/
public class RequestRun {
public static void main(String[] args) {
Userinfo userinfo = new Userinfo();
RequestAdmin admin = new RequestAdmin(userinfo);
RequestUser user = new RequestUser(userinfo);
admin.start();
user.start();
}
}
管理用户登录
普通用户登录
uername: user	role: 2
uername: admin	role: 1

我们看到输出是交替进行的,说明这两个线程是异步执行的,虽然我们没有在方法中添加synchronized关键字,但它们还是线程安全的。也就是说在多线程环境中局部变量都是线程安全的。

实例变量在多线程环境中的测试

/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

private int role = 0;

public void login(String username) {
try {
if ("admin".equals(username)) {
role = 1;
System.out.println("管理用户登录");
Thread.sleep(1000);
} else {
role = 2;
System.out.println("普通用户登录");
}
System.out.println(String.format("uername: %s\trole: %s", username, role));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


管理用户登录
普通用户登录
uername: user	role: 2
uername: admin	role: 2

我们看到实例变量在多线程中就可能会出现线程安全问题了。原因我们已经在其它篇里面说过,解决的办法就是在方法上添加synchronized关键字。

/**
* 用户登录
*
* @author Sama
* @author admin@jilinwula.com
* @date 2017-03-15 10:35
* @since 1.0.0
*/
public class Userinfo {

private int role = 0;

public synchronized void login(String username) {
try {
if ("admin".equals(username)) {
role = 1;
System.out.println("管理用户登录");
Thread.sleep(1000);
} else {
role = 2;
System.out.println("普通用户登录");
}
System.out.println(String.format("uername: %s\trole: %s", username, role));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
普通用户登录
uername: user	role: 2
管理用户登录
uername: admin	role: 1