程序员

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

2017-03-15  本文已影响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();

}

}

结果:

上一篇 下一篇

猜你喜欢

热点阅读