同步锁Lock是一种更强大的线程同步机制,通过显式定义同步锁对象来实现线程同步。同步锁提供了比同步代码块,同步方法更广泛的锁定操作,实现更灵活
Lock是控制多个线程对共享资源进行访问的工具,能够对共享资源进行独占访问,每次只能有一个线程对Lock对象加锁,线程访问共享资源之前需要先获得Lock对象,某些锁可能允许对共享资源并发访问。
【示例】使用ReentrantLock锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class MyClass{ //1.定义锁对象 private final ReentrantLock lock = new ReentrantLock(); //定义需要保证线程安全的方法 public void myMethod(){ //2.加锁 lock.lock(); try { //需要保证线程安全的代码 }finally { //3.释放锁 lock.unlock(); } } } |
- 加锁和释放锁需要放在线程安全的方法中;
- lock.unlock()放在finally语句中,不管发生异常与否,都需要释放锁
下面在银行账户类中增加一个同步锁
BankAccount.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
package com.rain.demo; import java.util.concurrent.locks.ReentrantLock; /** * Created by w-pc on 2017/02/24. * * 模拟银行账户 * */ public class BankAccount { //银行账户 private String bankNo; //银行余额 private double balance; //定义锁对象 private final ReentrantLock lock = new ReentrantLock(); //构造方法 public BankAccount(String bankNo,double balance) { this.bankNo = bankNo; this.balance = balance; } public void setBankNo(String bankNo) { this.bankNo = bankNo; } public void setBalance(double balance) { this.balance = balance; } public double getBalance() { return balance; } public String getBankNo() { return bankNo; } public void access(double money){ //加锁 lock.lock(); try { if (money < 0 && balance - money < 0) { System.out.println(Thread.currentThread().getName()+"操作失败"); return; } else { balance += money; System.out.println(Thread.currentThread().getName()+"操作成功,当前余额:" + balance); //设定休眠一毫秒,使其他线程得以执行 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } }finally { lock.unlock(); } } } |
结果:
1 2 3 4 5 6 7 |
T001操作成功,当前余额:2000.0 T002操作成功,当前余额:-1000.0 T003操作成功,当前余额:0.0 T004操作成功,当前余额:-2000.0 T005操作成功,当前余额:0.0 账户:60001002,余额:0.0 |