从demo到支持高并发

阅读更多

前言:

    Java语言作用很大,因有众多分门杂类的开源框架导致Javaer关注高并发细节问题偏少,常常被面试或者面试的时候,别人总是问你current的包,但是却很少人会询问你,“这段代码在高并发的情况下,会出现问题?我们应该如何改写呢?”所以本篇博客我想从最简单的demo,到支持高并发场景的,如果觉得过程中有问题问大家赐教。

 

案例:

   经典多线程并发问题就是生产者消费者问题,以下列子中,我会加入多种条件,而非一个纯种的生产者-消费者模式,可能很多人会觉得现在有了concurrent的PKG下的一大堆ArrayBlockQueue,但今天主题是如何优化改进。

demo,非安全的

 

public class UserAccount {
    private int balance;
    private long maxMoney = 5000000;
    private long minMOney = 1000000;

    public UserAccount(int balance) {
        this.balance = balance;
    }

    public void deposit(int amount) {
        while (balance + amount < maxMoney) {
            balance += amount;
            System.out.printf("存:" + balance);
        }

    }

    public void withdraw(int amount) {

        while (minMOney > balance - amount) {
            balance -= amount;
            System.out.println("取:" + balance);
        }
    }
}

 

第一步: 上面的代码很明显会出现并发问题,简单点我们加入synchronized

 

public class UserAccount {
    private int balance;
    private long maxMoney = 90000000;
    private long minMOney = 1000000;

    public UserAccount(int balance) {
        this.balance = balance;
    }

    public synchronized void deposit(int amount) {
//        synchronized (this) {
            while (balance + amount < maxMoney) {
                balance += amount;
                System.out.println("存:" + balance);
            }

        }
//    }

    public synchronized void withdraw(int amount) {

        while (minMOney > balance - amount) {
            balance -= amount;
            System.out.println("取:" + balance);
        }
    }
}
 第二步:有没有发现加入关键字synchronized后,是并发问题解决了,但是我们锁的范围太广了,不懂得可以看下synchronized的说明。(当两个并发线程访问同一个对象object中的这个 synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行)

 

    public void deposit(int amount) {
        synchronized (this) {
            while (balance + amount < maxMoney) {
                balance += amount;
                System.out.println("存:" + balance);
            }

        }
    }
 第四步:实际过程中,往往我们不会只有一个条件,这时候使用到ReentrantLock
  private final Lock monitor = new ReentrantLock();

    private final Condition low = monitor.newCondition();

    private final Condition high = monitor.newCondition();

    public UserAccount(int balance) {
        this.balance = balance;
    }

    public void deposit(int amount) {
        monitor.lock();
        try {
            while (balance + amount < maxMoney) {
                balance += amount;
                System.out.println("存:" + balance);
            }

            low.signal();
        } finally {
            monitor.unlock();
        }
    }
 第五步:锁升级,加入读写锁ReentrantReadWriteLock
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void read() {
        lock.readLock().lock();
        System.out.println(balance);
        lock.readLock().unlock();
    }
 
第六步:使用Atomic原子类
 
第七步:使用violate
 假设你的资源类中violate修饰的变量读的频繁程度远远大于写,那么violate修饰的变量就派上用场。
private volatile int value;

    public int getValue() {
        return value;
    }

    public int increment() {
        synchronized (this) {
            return value++;
        }
    }
 
第八步 异步处理
	CompletableFuture.supplyAsync(() -> {do something();}, taskExecutor);
 
未完待续...

你可能感兴趣的:(current,java,高并发,ReentrantLock)