Java对象及变量的并发访问
当多个线程同时对同一个对象中的实例变量进行并发访问时可能会产生线程安全问题。产生的后果就是”脏读”,即收到的数据其实是被更改过的。
如果访问的是方法中的变量,则不存在”非线程安全”问题
可以通过以下几种方式来解决,在对对象及变量并发访问过程中的安全问题
1. synchronize同步方法
2. 同步语句块
3. volatile关键字
synchronize同步方法
如果两个线程同时访问同一个对象的方法,不加控制,会出现意外的结果。通过用synchronize修饰方法,可以取得对象锁,那个线程先访问就先持有对象锁,其余的线程只能等待。
首先是没有用synchronize修饰的情况
public class HasSelfPrivateNum {
private int num = 0;
public void addI(String username){
try{
if (username.equals("a")){
num = 100;
System.out.println("a set over!");
Thread.sleep(2000);
}else {
num = 200;
System.out.println("b set over!");
}
System.out.println(username + " num=" + num);
}catch (Exception e){
e.printStackTrace();
}
}
}
public class SelfPrivateThreadA extends Thread{
private HasSelfPrivateNum num;
public SelfPrivateThreadA(HasSelfPrivateNum num){
this.num = num;
}
@Override
public void run() {
super.run();
num.addI("a");
}
}
public class SelfPrivateThreadB extends Thread{
private HasSelfPrivateNum num;
public SelfPrivateThreadB(HasSelfPrivateNum num){
this.num = num;
}
@Override
public void run() {
super.run();
num.addI("b");
}
}
测试类
public class HasSelfPrivateNumTest extends TestCase {
public void testAddI() throws Exception {
HasSelfPrivateNum numA = new HasSelfPrivateNum();
//HasSelfPrivateNum numB = new HasSelfPrivateNum();
SelfPrivateThreadA threadA = new SelfPrivateThreadA(numA);
threadA.start();
SelfPrivateThreadB threadB = new SelfPrivateThreadB(numA);
threadB.start();
Thread.sleep(1000 * 3);
}
}
预期结果应该是a num=100 b num=200
但是实际结果如下:
a set over!
b set over!
b num=200
a num=200