你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

synchronized 实现同步

2021-11-28 0:05:16

由于同一进程的多个线程共享同一块存储空间,在带来方便的同时,也带来了访问冲突 的问题。Java 语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线 程同时访问造成的这种问题。这套机制就是 synchronized 关键字。

synchronized 语法结构: 
synchronized(锁对象){
 	同步代码 
 }

synchronized 关键字使用时需要考虑的问题:
需要对那部分的代码在执行时具有线程互斥的能力(线程互斥:并行变串行)。
需要对哪些线程中的代码具有互斥能力(通过 synchronized 锁对象来决定)。
它包括两种用法:synchronized 方法和 synchronized 块

  1. synchronized 方法
    通过在方法声明中加入 synchronized 关键字来声明,语法如下: public synchronized void accessVal(int newVal);
    synchronized 在方法声明时使用:放在范围操作符(public)之后,返回类型声明(void) 之前。这时同一个对象下 synchronized 方法在多线程中执行时,该方法是同步的,即一次 只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就 是在 synchronized 方法内部的线程)执行完该方法后,别的线程才能进入。
  2. synchronized 块,synchronized 方法的缺陷:若将一个大的方法声明为 synchronized 将会大大影响效 率。Java 为我们提供了更好的解决办法,那就是 synchronized 块。 块可以让我们精确 地控制到具体的“成员变量”,缩小同步的范围,提高效率。
package com.yqq.app12;

/**
 * @Author yqq
 * @Date 2021/11/27 23:11
 * @Version 1.0
 */

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * 账户类
 */
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
class Account{
    //账号
    private String accountNo;
    //账户余额
    private double balance;

}

/**
 * 取款线程
 */
class DrawThread extends Thread{
    //账户对象
    private Account account;
    //取款金额
    private double drawMoney;
    public DrawThread(String name,Account account,double drawMoney){
        super(name);
        this.account = account;
        this.drawMoney = drawMoney;
    }
    @Override
    public void run() {
        synchronized (this.account){
            //判断当前余额是否大于或等于取款金额
            if (this.account.getBalance() >= this.drawMoney){
                System.out.println(this.getName()+" 取款成功!取款:"+this.drawMoney);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //修改余额
                this.account.setBalance(this.account.getBalance()-this.drawMoney);
                System.out.println("\t当前余额为:"+this.account.getBalance());
            }else {
                System.out.println("取款失败,余额不足");
            }
        }
    }
}
public class DrawMoneyThread {
    public static void main(String[] args) {
        Account account = new Account("10086",1000);
        new DrawThread("科比",account,600).start();
        new DrawThread("詹姆斯",account,700).start();
    }
}

在这里插入图片描述