`
cywhoyi
  • 浏览: 412639 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论
阅读更多

前言:

    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);
 
未完待续...
0
4
分享到:
评论
5 楼 cywhoyi 2016-02-29  
lionld23 写道
等着看呢,速度速度

我是抽空再写的,整篇文章范畴太大啦,牵扯到的东西尽量广一点
4 楼 lionld23 2016-02-26  
等着看呢,速度速度
3 楼 lzlg302 2016-02-25  
等待佳作
2 楼 cywhoyi 2016-02-25  
龘龘龘 写道
没了?没了?没了?没了?没了?没了?

我想哭啊,没保存,再重写过程中。。。
1 楼 龘龘龘 2016-02-25  
没了?没了?没了?没了?没了?没了?

相关推荐

Global site tag (gtag.js) - Google Analytics