JUC并发编程 -- 保护共享资源(加锁实现 & 无锁实现)

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC并发编程 -- 保护共享资源(加锁实现 & 无锁实现)相关的知识,希望对你有一定的参考价值。

1. 保护共享资源


1.1 不安全的实现:

账户接口:

interface Account {
    // 获取余额
    Integer getBalance();

    // 取款
    void withdraw(Integer amount);

    /**
     * 方法内会启动 1000 个线程,每个线程做 -10 元 的操作
     * 如果初始余额为 10000 那么正确的结果应当是 0
     */
    static void demo(Account account) {
        List<Thread> ts = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            ts.add(new Thread(() -> {
                account.withdraw(10);
            }));
        }
        long start = System.nanoTime();
        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        long end = System.nanoTime();
        System.out.println(account.getBalance()
                + " cost: " + (end - start) / 1000_000 + " ms");
    }
}

不安全的实现类:

class AccountUnsafe implements Account {

    private Integer balance;

    public AccountUnsafe(Integer balance) {
        this.balance = balance;
    }

    @Override
    public Integer getBalance() {
        synchronized (this) {
            return this.balance;
        }
    }

    @Override
    public void withdraw(Integer amount) {
        this.balance -= amount;
    }
}

运行测试:

package tian;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class TestAccount {
    public static void main(String[] args) {
        Account account = new AccountUnsafe(10000);
        Account.demo(account);
    }
}

运行结果:


1.2 加锁实现

安全的实现类:

class AccountUnsafe implements Account {

    private Integer balance;

    public AccountUnsafe(Integer balance) {
        this.balance = balance;
    }

    @Override
    public Integer getBalance() {
        synchronized (this) {
            return this.balance;
        }
    }

    @Override
    public void withdraw(Integer amount) {
        synchronized (this) {
            this.balance -= amount;
        }
    }
}

运行结果:


1.3 无锁实现:

无锁实现:

package tian;


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class TestAccount {
    public static void main(String[] args) {
        Account account = new AccountCas(10000);
        Account.demo(account);
    }
}

class AccountCas implements Account {
    // 原子Integer类
    private AtomicInteger balance;

    public AccountCas(int balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
        return balance.get();
    }

    @Override
    public void withdraw(Integer amount) {
        while (true) {
            // 获取余额的最新值
            int prev = balance.get();
            // 要修改的余额
            int next = prev - amount;
            // 真正修改 返沪一个布尔值 修改成功才会退出循环
            if (balance.compareAndSet(prev, next)) {
                break;
            }
        }
    }
}

运行结果:


1.4 无锁实现补充:

withdraw方法的另一种实现方式:

class AccountCas implements Account {
    private AtomicInteger balance;

    public AccountCas(int balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
        return balance.get();
    }

    @Override
    public void withdraw(Integer amount) {
        balance.getAndAdd(-1 * amount);
    }
}


以上是关于JUC并发编程 -- 保护共享资源(加锁实现 & 无锁实现)的主要内容,如果未能解决你的问题,请参考以下文章

JUC学习之共享模型工具之JUC并发工具包上

秋招之路9:juc并发

JUC并发编程 共享模式之工具 JUC 读写锁 ReentrantReadWriteLock -- ReentrantReadWriteLock(不可重入锁)使用 & 注意事项

并发编程中,你加的锁未必安全

JUC并发编程 多线程设计模式 -- 同步模式之保护性暂停(定义 & 实现 & 带超时版 GuardedObject)

JUC并发编程 -- synchronized 原理进阶之轻量级锁 & 锁膨胀