知识大全 Java多线程同步-BusyFlag或Lock
Posted 知
篇首语:奋斗者在汗水汇集的江河里,将事业之舟驶到了理想的彼岸。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java多线程同步-BusyFlag或Lock相关的知识,希望对你有一定的参考价值。
Java多线程同步-BusyFlag或Lock 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
我们首先开发一个BusyFlag的类 类似于C++中的Simaphore
- public class BusyFlag protected Thread busyflag = null; protected int busycount = ; public synchronized void getBusyFlag() while (tryGetBusyFlag() == false) try wait(); catch ( Exception e) private synchronized boolean tryGetBusyFlag() if (busyflag == null) busyflag = Thread currentThread(); busycount = ; return true; if (busyflag == Thread currentThread()) busycount++; return true; return false; public synchronized void freeBusyFlag() if(getOwner()== Thread currentThread()) busycount ; if(busycount== ) busyflag = null; notify(); public synchronized Thread getOwner() return busyflag;
注 参考Scott Oaks & Henry Wong《Java Thread》BusyFlag有 个公开方法 getBusyFlag freeBusyFlag getOwner 分别用于获取忙标志 释放忙标志和获取当前占用忙标志的线程 使用这个BusyFlag也非常地简单 只需要在需要锁定的地方 调用BusyFlag的getBusyFlag() 在对锁定的资源使用完毕时 再调用改BusyFlag的freeBusyFlag()即可 下面我们开始改造上篇中的Account和ATM类 并应用BusyFlag工具类使得同时只有一个线程能够访问同一个账户的目标得以实现 首先 要改造Account类 在Account中内置了一个BusyFlag对象 并通过此标志对象对Account进行锁定和解锁
- import java util Collections; import java util HashMap; import java util Map; class Account String name; //float amount; BusyFlag flag = new BusyFlag(); //使用一个Map模拟持久存储 static Map storage = new HashMap(); static storage put( John new Float( f)); storage put( Mike new Float( f)); static Map accounts = Collections synchronizedMap( new HashMap()); private Account( String name) this name = name; //this amount = ((Float)storage get(name)) floatValue(); public synchronized static Account getAccount ( String name) if (accounts get(name) == null) accounts put(name new Account(name)); return (Account) accounts get(name); public synchronized void deposit( float amt) float amount = (( Float)storage get(name)) floatValue(); storage put(name new Float(amount + amt)); public synchronized void withdraw( float amt) throws InsufficientBalanceException float amount = (( Float)storage get(name)) floatValue(); if (amount >= amt) amount = amt; else throw new InsufficientBalanceException(); storage put(name new Float(amount)); public float getBalance() float amount = (( Float)storage get(name)) floatValue(); return amount; public void lock() flag getBusyFlag(); public void unlock() flag freeBusyFlag();
新的Account提供了两个用于锁定的方法 lock()和unlock() 供Account对象的客户端在需要时锁定Account和解锁Account Account通过委托给BusyFlag来提供这个机制 另外 大家也发现了 新的Account中提供了对Account对象的缓存 同时去除了public的构造方法 改为使用一个静态工厂方法供用户获取Account的实例 这样做也是有必要的 因为我们希望所有的ATM机同时只能有一个能够对同一个Account进行操作 我们在Account上的锁定是对一个特定Account对象进行加锁 如果多个ATM同时实例化多个同一个user的Account对象 那么仍然可以同时操作同一个账户 所以 要使用这种机制就必须保证Account对象在系统中的唯一性 所以 这儿使用一个Account的缓存 并将Account的构造方法变为私有的 你也可以说 通过在Account类锁上进行同步 即将Account中的BusyFlag对象声明为static的 但这样就使同时只能有一台ATM机进行操作了 这样 在一台ATM机在操作时 全市其它的所有的ATM机都必须等待 另外必须注意的一点是 Account中的getAccount()方法必须同步 否则 将有可能生成多个Account对象 因为可能多个线程同时到达这个方法 并监测到accounts中没有 John 的Account实例 从而实例化多个John的Account实例 sATM类只需作少量改动 在login方法中锁定Account 在logout方法中解锁
- public class ATM Account acc; //作为演示 省略了密码验证 public synchronized boolean login( String name) if (acc != null) throw new IllegalArgumentException( Already logged in! ); acc = Account getAccount(name); acc lock(); return true; public void deposit( float amt) acc deposit(amt); public void withdraw( float amt) throws InsufficientBalanceException acc withdraw(amt); public float getBalance() return acc getBalance(); public synchronized void logout () acc unlock(); acc = null;
- Lock l = ; l lock(); try // access the resource protected by this lock finally l unlock();
相关参考