java多线程安全问题的解除步骤
1.明确多线程执行代码。(run方法中的代码都是多线程执行代码,如果在run方法体中调用了其他方法,那么其他方法所包含的代码也是多线程执行代码)
2.明确多线程共享数据。(创建多线程对象时传递给Thread(Object o)构造函数的对象,是共享数据(注:对象中的属性、以及包含的其他对象都是共享数据),当对象中包含其他的对象时,那么其他的对象中的所有数据也都是共享数据。
3.明确多线程执行代码中操作了共享数据的代码,将操作了共享数据的代码放入synchronized(Object o )方法体中,这样线程安全问题就解决。(注:还可使用另一种行式的代码来处理操作了共享数据的代码。它们产生的作用是一样的,只是代码的形式不同)
另一种行式:假如add(int n)方法封装了操作共享数据的代码,只需将synchronized作为修饰符,修饰add(int n)方法即可。synchronized修饰符位于访问权限修饰符之后,返回值类型之前。注:常用技巧,定义一个synchronized修饰的函数,将某处操作了共享数据的代码移到函数中,再在代码的原始位置调用该函数。
如: public synchronized void add(int n){
//将共享数据的值加上n
sum+=n;
//将共享数据的值输出
System.out.println("sum="+sum);
}
示例代码:
class Bank{
//共享数据对象中包含了Bank对象,所Bank对象中的sum也是共享数据
private int sum;
Object obj = new Object();
public void add(int n){
//将操作了共享数据sum的代码放入synchronized(Object o )方法体中
synchronized(obj ){
//将共享数据的值加上n
sum+=n;
//将共享数据的值输出
System.out.println("sum="+sum);
}
}
}
//定义共享数据对象的类。
class Cus implements Runnable{
//在共享数据对象的类创建一个Bank,所以Bank也是一个共享数据,Bank对象中所包含的数据也都是共享数据。
private Bank b = new Bank();
public void run(){
//run方法体中的代码都是多线程执行的代码。
for(int x=0; x<3; x++){
//run方法体中调用了add(int n)方法,add(int n)方法中的代码也是多线程执行的代码。
b.add(100);
}
}
}
class BankDemo{
public static void main(){
//创建Cus对象,该对象为共享数据
Cus c = new Cus();
// 创建两个线程对象,并共享数据传给两个线程对象。
Thread t1= new Thread(c);
Thread t2= new Thread(c);
//开启两个线程
t1.start();
t1.start();
}
}
|