在什么情况下回出现线程安全问题:
1.存在两个或者两个以上的线程对象,而且线程之间共享一个资源
2.有多个语句操作共享资源
线程安全问题解决方案:
方式一:同步代码块
格式:
synchronized(锁对象){
需要被同步的代码;
}
同步代码块需要注意的事项:
1.所对象可以为任意一个对象
2.在同步代码块中,调用sleep方法并不会释放锁对象
3.同步代码块只有真正存在线程安全问题才使用同步代码块,否则会降低效率
4.多线程操作的锁对象是唯一共享的,否则无效
方式二:同步函数
同步函数就是使用synchronized修饰一个函数
同步函数要注意的事项:
1.如果是一个非静态的同步函数锁对象是this对象。如果是静态的同步函数的锁对象是当前函数所属的类的字节码文件(class对象)
2.同步函数的锁对象是固定的
推荐使用:同步代码块
原因:1.同步代码块的锁对象可以由我们随意指定,方便控制。同步函数的锁对象是固定的,不能由我们指定
2.同步代码块可以很方便控制需要被同步代码的范围。同步函数必须是整个函数的所有代码都被同步了
java中的同步机制解决了线程安全问题,同时也引发了死锁现象
死锁现象出现的根本原因:
1.存在两个或两个以上的线程
2.存在两个或两个以上的共享资源
练习:一个银行账户里有5000块钱,两个人同时取,一次取1000
class OutMoney extends Thread{
static int money=5000;
static Object o=new Object();
public OutMoney(String name){
super(name);
}
public void run(){
while(true){
synchronized(o){
if(money>0){
System.out.println(Thread.currentThread().getName()+"取出了1000钱,还剩"+(money-1000));
money-=1000;
}else{
System.out.println("钱取完了");
break;
}
}
}
}
}
public class Test19 {
public static void main(String[] args) {
// TODO Auto-generated method stub
OutMoney thread1=new OutMoney("男");
OutMoney thread2=new OutMoney("女");
thread1.start();
thread2.start();
}
}