【狂神说Java】线程同步方法&同步块
同步方法
- 对方法加上
synchronized关键字 - 有
synchronized的方法调用时都需要得到该方法的锁,否则无法执行。线程执行完毕释放锁后,其他线程才能获得这个锁。 - 若将一个大的方法申明为
synchronized会影响效率。- 方法里面需要修改内容菜需要锁,锁太多,浪费资源。
安全买票
public class SafeBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
// new三个线程同时操作一个对象
new Thread(buyTicket,"a").start();
new Thread(buyTicket,"b").start();
new Thread(buyTicket,"c").start();
}
}
class BuyTicket implements Runnable{
private int ticketNums = 10;//总共10张票
private boolean flag = true;
private synchronized void buy() {
// 买票
if (ticketNums <= 0) {
flag = false;
return;
}try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "抢到了第" + (ticketNums--) + "张票");
}
@Override
public void run() {
while (flag) {
buy();
}
}
}
同步块
- 同步块:
synchronized(Obj){代码} - Obj称之为同步监视器,需要锁的对象是增删改查的对象
- Obj可以是任何对象,但是推荐使用共享资源作为同步监视器
- 同步方法中无需指定同步监视器,因为同步方法的监视器就是
this就是它本身,或者是class
- 同步监视器执行过程
- 第一个线程访问,锁定同步监视器,执行其中代码
- 第二个线程访问,发现同步监视器被锁定,无法访问
- 第一个线程访问完毕,解锁同步监视器
- 第二个线程访问,发现同步监视器没有锁,然后锁定访问
public class SafeDrawing {
public static void main(String[] args) {
Account account = new Account(200,"1123");
Drawing a = new Drawing(account,100,0,"aaa");
Drawing b = new Drawing(account,200,0,"bbb");
a.start();
b.start();
}
}
class Account{
public Account(int money, String id) {
this.money = money;
this.id = id;
}
// 银行账户
int money;// 余额
String id;// 账号
}
class Drawing extends Thread{
Account account; // 账户
int drawingMoney; //取钱
int nowMoney; // 手上的钱
public Drawing(Account id,int drawingMoney,int nowMoney,String name){
super(name);
this.account = id;
this.drawingMoney = drawingMoney;
this.nowMoney = nowMoney;
}
@Override
public void run() {
// 同步代码块
synchronized (account){
// 判断有没有钱
if (account.money < drawingMoney){
System.out.println("钱不够");
return;
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 账户上的钱
account.money -= drawingMoney;
// 你手里的钱
nowMoney += drawingMoney;
System.out.println(account.id+ "账户余额为:"+ account.money);
System.out.println(this.getName() + "手里的钱为:"+ nowMoney);
}
}
}

浙公网安备 33010602011771号