在方法返回值类型前加上 synchronized ,意味着一旦有线程执行了该方法,该线程就上锁了,只有到该方法执行完,也就是return 后,锁才被释放,这个过程中从始至终只有一个线程操作。也就是线程同步。
例如:
public synchronized static void main(String[] args){}
private synchronized void run(){}
//以下也行
synchronized private void run(){}
或者 同步代码块
private void run(){
synchronized(this){
}
}
首先来看为什么会有线程同步:
java中默认是异步线程
【举例】
一张电子饭卡小明和小红共用(电子卡才有可能两人在同一时间使用)
public class Card {
private static int money = 80;
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
//取款
public void chargeMoney(int money){
this.money -= money ;
}
}
public class People implements Runnable{
//在People初始化时就已经初始化Card
private Card card = new Card();
@Override
public void run() {
for(int i = 0 ; i < 5 ;i++){
chargeMoney(10);
if(card.getMoney()<0){
System.out.println("卡里没钱了!");
}
}
}
public void chargeMoney(int mon) {
if(card.getMoney() >= mon){
try {
Thread.sleep(2000);
}catch (InterruptedException e){
e.printStackTrace();
}
card.chargeMoney(mon);
System.out.println(Thread.currentThread().getName()+" 先生/女士,已成功扣款 "+mon+" 元,余额为 "+ card.getMoney());
}else{
System.out.println(Thread.currentThread().getName()+" 先生/女士,不好意思,你的饭卡已透支,余额仅有 "+card.getMoney());
}
}
}
public class Main {
public static void main(String[] args) {
People people = new People();
Thread thread1 = new Thread(people,"小明");
Thread thread2 = new Thread(people,"小红");
thread1.start();
thread2.start();
}
}
运行结果:
由于默认是异步线程,所以当两人同时消费时,就会出现上述混乱情况(当一个人付完款显示余额时,其实那个余额并不是实际上的)。
而实际生活中,为了避免这种情况的发生,最好的方法就是限定同一时间只能有一个人付款,也就是只允许某个线程对资源进行操作,也就是锁的概念了。
改进方法:在线程执行方法前加上 synchronized ,使执行该方法只能是一个线程。
public synchronized void run() {
for(int i = 0 ; i < 5 ;i++){
chargeMoney(10);
if(card.getMoney()<0){
System.out.println("卡里没钱了!");
}
}
}
运行结果:
这里是因为连续五次
进行扣款,所以一直都是一个线程在操作,实际过程就是小明付完一次后,小红就能付了。
这就是同步的意义。