使用synchronized关键字
线程不安全的例子:
线程不安全主要存在于“实例变量”,如果是方法内部的私有变量,则不存在“非线程安全”的问题
示例代码:
package a;
class HasSelfPrivateNum{
public void addI(String username) {
int num=0;
if(username.equals("a")) {
num=100;
System.out.println("a set over!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
num=200;
System.out.println("b set over!");
}
System.out.println(username+" num="+num);
}
}
class Thread_A extends Thread{
private HasSelfPrivateNum numRef;
public Thread_A(HasSelfPrivateNum numRef) {
this.numRef=numRef;
}
@Override
public void run() {
numRef.addI("a");
}
}
class Thread_B extends Thread{
private HasSelfPrivateNum numRef;
public Thread_B(HasSelfPrivateNum numRef) {
this.numRef=numRef;
}
@Override
public void run() {
numRef.addI("b");
}
}
public class SynTest2 {
public static void main(String[] args) {
HasSelfPrivateNum numRef=new HasSelfPrivateNum();
Thread_A athread=new Thread_A(numRef);
athread.start();
Thread_B bthread=new Thread_B(numRef);
bthread.start();
}
}
输出结果
a set over!
b set over!
b num=200
a num=100
稍作修改
将synchronized关键字加到addI()方法前面
synchronized public void addI(String username) {
int num=0;
if(username.equals("a")) {
num=100;
System.out.println("a set over!");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
num=200;
System.out.println("b set over!");
}
System.out.println(username+" num="+num);
}
输出结果:
a set over!
a num=100
b set over!
b num=200
结果分析:
synchronized关键字是对象进行加锁,在一个线程取得了锁之后,另一个线程只能等待其执行完成并且释放锁。
再次修改:
将main方法修改为:
public static void main(String[] args) {
HasSelfPrivateNum numRef=new HasSelfPrivateNum();
HasSelfPrivateNum numRef1=new HasSelfPrivateNum();
Thread_A athread=new Thread_A(numRef);
athread.start();
Thread_B bthread=new Thread_B(numRef1);
bthread.start();
}
输出结果:
a set over!
b set over!
b num=200
a num=100
结果分析:
此处定义了两个HasSelfPrivateNum对象。并且两个对象的锁分别被两个线程持有。
此时两者的运行互不干涉。