- 如果是方法中的变量,不存在线程安全问题。
- 方法中的变量代码片段:
public class HasSelfPrivateNum {
public void addI(String userName) {
// 这里的num变量是存在于addI这个方法里面的
int num = 0;
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 (InterruptedException e) {
e.printStackTrace();
}
}
}
- 线程a:
public class ThreadA extends Thread{
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef){
super();
this.numRef = numRef;
}
@Override
public void run(){
super.run();
numRef.addI("a");
}
}
- 线程b:
public class ThreadB extends Thread {
private HasSelfPrivateNum numRef;
public ThreadB(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("b");
}
}
- 测试类:
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef = new HasSelfPrivateNum();
ThreadA threadA = new ThreadA(numRef);
threadA.start();
ThreadB threadB = new ThreadB(numRef);
threadB.start();
}
}
- 测试结果:
- 再来测试一下,如果变量不是在方法中,而是在class中,结果如何?
- 对象仅有一个实例变量,可能被覆盖
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 (InterruptedException e) {
e.printStackTrace();
}
}
}
其余代码不变进行测试一下: 这里可以看到测试的结果已经变了,a num也已经变成了200,解决的方法最直接的一种就是加上锁。通过再次测试加锁结果可以看到,已经能够保证线程安全,不会发生“脏读”读到其他线程修改结果的情况了。 ==结论:两个线程先后访问同一个对象的同步方法是线程安全的!==
- 多个锁多个对象的情况 如果有多个对象的情况下,代码如下:
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2= new HasSelfPrivateNum();
ThreadA threadA = new ThreadA(numRef1);
threadA.start();
ThreadB threadB = new ThreadB(numRef2);
threadB.start();
}
}
测试结果如下: ==结论:关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法(函数)当作锁,所以在上面的示例中,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁Lock,那么其他线程只能呈等待状态,前提是多个线程访问的是同一个对象。但如果多个线程访问多个对象,则JVM会创建多个锁。上面的示例就是创建了2个HasSelfPrivateNum.java类的对象,所以就会产生出2个锁。==
- 继续测试验证
- 如果是加上了锁,则会产生同步现象 ⚠️ 调用用关键字synchronized声明的方法一定是排队运行的。另外需要牢牢记住“共享”这两个字,只有共享资源的读写访问才需要同步化,如果不是共享资源,那么根本就没有同步的必要。
- 结论:
标签:HasSelfPrivateNum,变量,numRef,安全性,num,线程,new,多线程,public From: https://blog.51cto.com/u_15927490/73781321)A线程先持有object对象的Lock锁,B线程可以以异步的方式调用object对象中的非synchronized类型的方法。2)A线程先持有object对象的Lock锁,B线程如果在这时调用object对象中的synchronized类型的方法则需等待,也就是同步。