美文网首页程序员
Java多线程同步3——同步锁

Java多线程同步3——同步锁

作者: 码上人生 | 来源:发表于2017-03-15 20:07 被阅读0次

    Java提供了一种更强大的线程同步机制——通过显示定义同步锁对象来实现同步,同步锁由Lock对象充当。

    Lock是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独立访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象

    在实现线程安全的控制中,比较常用的是ReentrantLock(可重写入锁)。使用该Lock对象可以显示地加锁,释放锁,通常使用ReentrantLock格式如下:

    class x{

      private final ReentrantLock lock=new ReentrantLock();

     public void m(){

    lock.lock();

    try{

    //需要保证线程安全的代码

    }finally{

    lock.unlock();

    }

    }

    }

    通过使用ReentrantLock的方法修改前文所提到的取钱问题。

    package com.eduask.java.thread.sync.lock;

    import java.util.concurrent.locks.*;

    public class Account

    {

    // 定义锁对象

    private final ReentrantLock lock = new ReentrantLock();

    // // 封装账户编号、账户余额的两个成员变量

    private String accountNo;

    private double balance;

    public Account(){}

    // 构造器

    public Account(String accountNo , double balance)

    {

    this.accountNo = accountNo;

    this.balance = balance;

    }

    public void setAccountNo(String accountNo)

    {

    this.accountNo = accountNo;

    }

    public String getAccountNo()

    {

    return this.accountNo;

    }

    public double getBalance()

    {

    return this.balance;

    }

    // 提供一个线程安全draw()方法来完成取钱操作

    public void draw(double drawAmount)

    {

    // 加锁

    lock.lock();

    try

    {

    // 账户余额大于取钱数目

    if (balance >= drawAmount)

    {

    System.out.println(Thread.currentThread().getName()

    + "取钱成功!吐出钞票:" + drawAmount);

    try

    {

    Thread.sleep(1);

    }

    catch (InterruptedException ex)

    {

    ex.printStackTrace();

    }

    // 修改余额

    balance -= drawAmount;

    System.out.println("\t余额为" + balance);

    }

    else

    {

    System.out.println(Thread.currentThread().getName()

    + "取钱失败!余额不足!");

    }

    }

    finally

    {

    // 修改完成,释放锁

    lock.unlock();

    }

    }

    public int hashCode()

    {

    return accountNo.hashCode();

    }

    public boolean equals(Object obj)

    {

    if(this == obj)

    return true;

    if (obj !=null

    && obj.getClass() == Account.class)

    {

    Account target = (Account)obj;

    return target.getAccountNo().equals(accountNo);

    }

    return false;

    }

    }

    模仿取钱的多线程

    package com.eduask.java.thread.sync.lock;

    public class DrawThread extends Thread

    {

    // 模拟用户账户

    private Account account;

    // 当前取钱线程所希望取的钱数

    private double drawAmount;

    public DrawThread(String name , Account account

    , double drawAmount)

    {

    super(name);

    this.account = account;

    this.drawAmount = drawAmount;

    }

    public void run()

    {

    account.draw(drawAmount);

    }

    }

    测试类

    package com.eduask.java.thread.sync.lock;

    public class DrawTest

    {

    public static void main(String[] args)

    {

    Account acct = new Account("1234567" , 1000);

    new DrawThread("A" , acct , 800).start();

    new DrawThread("B" , acct , 800).start();

    }

    }

    结果:

    相关文章

      网友评论

        本文标题:Java多线程同步3——同步锁

        本文链接:https://www.haomeiwen.com/subject/pqdrnttx.html