Java线程:新特征-锁(2)

说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限.它和后者都是单独的实现,彼此之间没有继承或实现的关系.然后就是总结这个锁机制的特性了:

  1. 重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。
  2. WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(1)。
  3. ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。
  4. 不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。
  5. readLock只有释放后,writeLock才能获得锁。
  6. readLock在没有被释放的时候可以被多个线程同时读取,此时还可以重入writeLock锁。
  7. writeLock在没有被释放的时候其他锁不能进入,也不能重入readLock锁,直到writeLock被解锁 。

 

ReentrantReadWriteLock会使用两把锁来解决问题:一个读锁,一个写锁。

  • 线程进入读锁的前提条件:
          没有其他线程的写锁
          没有写请求或者有写请求,但调用线程和持有锁的线程是同一个。
  • 线程进入写锁的前提条件:
          没有其他线程的读锁
          没有其他线程的写锁
import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.locks.ReadWriteLock;

import java.util.concurrent.locks.ReentrantReadWriteLock;



/**

* Java线程:锁

*

* @author leizhimin 2009-11-5 10:57:29

*/

public class LockT2 {

    public static void main(String[] args) {

        //创建并发访问的账户

        MyCount2 myCount = new MyCount2("95599200901215522", 10000);

        //创建一个锁对象

        ReadWriteLock lock = new ReentrantReadWriteLock(false);

        //创建一个线程池

        ExecutorService pool = Executors.newFixedThreadPool(10);

        //创建一些并发访问用户,一个信用卡,存的存,取的取,好热闹啊

        User2 u1 = new User2("张三", myCount, -4000, lock, false);

        User2 u2 = new User2("李四", myCount, 6000, lock, false);

        User2 u3 = new User2("王五", myCount, -8000, lock, false);

        User2 u4 = new User2("孙六", myCount, 800, lock, false);

        User2 u5 = new User2("赵七", myCount, 0, lock, true);



        //在线程池中执行各个用户的操作

        pool.execute(u1);

        pool.execute(u2);

        pool.execute(u3);

        pool.execute(u4);

        pool.execute(u5);

        //关闭线程池

        pool.shutdown();

    }

}

/**

* 信用卡的用户

*/

class User2 implements Runnable {

    private String name; //用户名 

    private MyCount2 myCount; //所要操作的账户

    private int iocash; //操作的金额,当然有正负之分了

    private ReadWriteLock myLock; //执行操作所需的锁对象

    private boolean ischeck; //是否查询



    User2(String name, MyCount2 myCount, int iocash, ReadWriteLock myLock, boolean ischeck) {

        this.name = name;

        this.myCount = myCount;

        this.iocash = iocash;

        this.myLock = myLock;

        this.ischeck = ischeck;

    }



    public void run() {

        if (ischeck) {

            //获取读锁

            myLock.readLock().lock();



            System.out.println("读:" + name + "正在查询" + myCount + "账户,当前金额为" + myCount.getCash());

            //释放读锁

            myLock.readLock().unlock();

        }

        else {

            //获取写锁

            myLock.writeLock().lock();

//执行现金业务 

            System.out.println("写:" + name + "正在操作" + myCount + "账户,金额为" + iocash + ",当前金额为" + myCount.getCash());

            myCount.setCash(myCount.getCash() + iocash);

            System.out.println("写:" + name + "操作" + myCount + "账户成功,金额为" + iocash + ",当前金额为" + myCount.getCash());

            //释放写锁

            myLock.writeLock().unlock();

        }

    }

}

/**

* 信用卡账户,可随意透支 

*/

class MyCount2 {

    private String oid; //账号

    private int cash; //账户余额 



    MyCount2(String oid, int cash) {

        this.oid = oid;

        this.cash = cash;

    }



    public String getOid() {

        return oid;

    }



    public void setOid(String oid) {

        this.oid = oid;

    }



    public int getCash() {

        return cash;

    }



    public void setCash(int cash) {

        this.cash = cash;

    }



    @Override

    public String toString() {

        return "MyCount{" + "oid='" + oid + '\'' + ", cash=" + cash + '}';

    }

}

 打印结果:
写:张三正在操作MyCount{oid='95599200901215522', cash=10000}账户,金额为-4000,当前金额为10000
写:张三操作MyCount{oid='95599200901215522', cash=6000}账户成功,金额为-4000,当前金额为6000
写:孙六正在操作MyCount{oid='95599200901215522', cash=6000}账户,金额为800,当前金额为6000
写:孙六操作MyCount{oid='95599200901215522', cash=6800}账户成功,金额为800,当前金额为6800
写:李四正在操作MyCount{oid='95599200901215522', cash=6800}账户,金额为6000,当前金额为6800
写:李四操作MyCount{oid='95599200901215522', cash=12800}账户成功,金额为6000,当前金额为12800
写:王五正在操作MyCount{oid='95599200901215522', cash=12800}账户,金额为-8000,当前金额为12800
写:王五操作MyCount{oid='95599200901215522', cash=4800}账户成功,金额为-8000,当前金额为4800
读:赵七正在查询MyCount{oid='95599200901215522', cash=4800}账户,当前金额为4800

你可能感兴趣的:(java线程)