一、特性:方法中的变量不存在非线程安全问题,永远都是线程安全的,这是方法内部的变量是私有的特性决定的。
示例代码;
1. HasSelfPrivateNum.java
package com.threadtest6;
public class HasSelfPrivateNum {
public void addI(String username){
try {
int num = 0;
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();
}
}
}
2. ThreadA.java
package com.threadtest6;
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");
}
}
3. ThreadB.java
package com.threadtest6;
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");
}
}
4. Run.java
package com.threadtest6;
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef = new HasSelfPrivateNum();
ThreadA athread = new ThreadA(numRef);
ThreadB bthread = new ThreadB(numRef);
athread.start();
bthread.start();
}
}
运行结果:
二、实例变量非线程安全
将HasSelfPrivateNum.java代码如下调整:
package com.threadtest7;
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();
}
}
}
则运行结果如下:
出现这个现象的原因是两个线程同时访问一个没有同步的方法,若要实现线程安全,则只需要在方法前加上关键字synchronized即可。
三、多个实例对象将会产生多个锁
run.java代码如下调整:
package com.threadtest7;
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
ThreadA athread = new ThreadA(numRef1);
athread.start();
ThreadB bthread = new ThreadB(numRef2);
bthread.start();
}
}
运行结果:
上述示例为两个线程分别访问同一个类的两个不同实例的相同名称的同步方法,效果是以异步方式运行,原理是关键字synchronized取得的锁都是对象锁,而不是把一段代码或者方法当作锁,如果多个线程访问多个对象,则JVM会创建多个锁。