Java线程同步

一:什么是线程同步?

1.线程同步是解决线程安全问题的方案。

2.线程同步是让多个线程实现先后依次访问共享资源,这样就解决了安全问题。

3.线程同步的常见方案

加锁:每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能再加锁进来

二:加锁的方式

1.方式一:同步代码块

作用:把访问共享资源的核心代码给上锁,以保证线程安全。

原理:每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行。

同步锁注意事项:

对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug。

锁对象的使用规范:

①建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。

②对于静态方法建议使用字节码(类名.class)对象作为锁对象。

public void DrawMoney(double money) {
String name = Thread.currentThread().getName();
synchronized (this) {
    if (this.money >= money){
        System.out.println(name+"来取钱成功"+"取钱"+money+"元!");
        this.money -= money;
        System.out.println(name+"取钱后余额为"+this.money);
    }else {
        System.out.println(name+"取钱失败,余额不足~~");
    }
}
}

2.方式二:同步方法

作用:把访问共享资源的核心方法给上锁,以保证线程安全。

原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行。

同步方法的底层原理:

①同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码。

②如果方法是实例方法:同步方法默认用this作为的锁对象。

③如果方法是静态方法:同步方法默认用类名.class作为锁对象。

public synchronized void DrawMoney(double money) {
    String name = Thread.currentThread().getName();
    if (this.money >= money){
        System.out.println(name+"来取钱成功"+"取钱"+money+"元!");
        this.money -= money;
        System.out.println(name+"取钱后余额为"+this.money);
    }else {
        System.out.println(name+"取钱失败,余额不足~~");
    }
}

--------------------------------------------------------------------------------------

同步方法与同步代码块相比较:

范围上:同步代码块锁的范围更小,同步方法锁的范围更大。

可读性:同步方法更好。

3.方式三:Lock锁

Lock锁是JDK5开始提供的一个新的操作锁定,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大。

Lock锁是接口不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象

构造器:

ReentrantLock() 获取Lock锁的实现类对象

方法:

lock() 获得锁

unlock() 释放锁

public Lock lk = new ReentrantLock();
	public void DrawMoney(double money) {
	String name = Thread.currentThread().getName();
	try {
    	lk.lock();
    	if (this.money >= money){
        	System.out.println(name+"来取钱成功"+"取钱"+money+"元!");
        	this.money -= money;
        	System.out.println(name+"取钱后余额为"+this.money);
    	}else {
        	System.out.println(name+"取钱失败,余额不足~~");
    	}
	} catch (Exception e) {
    	throw new RuntimeException(e);
	} finally {
    		lk.unlock();
		}
	}

三:银行取钱案例(Lock锁方式)

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Account {
    private String cardId;
    private double money;
    public Lock lk = new ReentrantLock();

    public Account() {
    }
    public void DrawMoney(double money) {
        String name = Thread.currentThread().getName();
        try {
            lk.lock();
            if (this.money >= money){
                System.out.println(name+"来取钱成功"+"取钱"+money+"元!");
                this.money -= money;
                System.out.println(name+"取钱后余额为"+this.money);
            }else {
                System.out.println(name+"取钱失败,余额不足~~");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lk.unlock();
        }
    }
    public Account(String cardId, double money) {
        this.cardId = cardId;
        this.money = money;
    }

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }


}

public class DrawThread extends Thread{
    public Account acc;
    public DrawThread(Account acc, String name){
        super(name);
        this.acc = acc;
    }
    @Override
    public void run() {
        acc.DrawMoney(100000);
    }
}

public class ThreadTest5 {
    public static void main(String[] args) {
        Account acc1 = new Account("IBI-1",100000);
        new DrawThread(acc1,"小红").start();
        new DrawThread(acc1,"小明").start();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值