线程同步学习一

线程不安全举例,存钱取钱  账户余额有时为负数。

package threadStudy;

/**
 * 模拟线程不安全 存钱取钱
 */

public class SynTest1 {
    public static void main(String[] args) {
        Account account = new Account("王五的银行卡", 1000);
        Withdraw withdraw1 = new Withdraw(account, 800);
        Withdraw withdraw2 = new Withdraw(account, 700);
        Thread t1 = new Thread(withdraw1, "husband");
        Thread t2 = new Thread(withdraw2, "wife");
        t1.start();
        t2.start();
    }
}

// 账户
class Account {
    private String name;
    private int money;

    public Account(String name, int money) {
        this.name = name;
        this.money = money;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

}

// 取钱的线程

class Withdraw implements Runnable {

    private Account account;
    private int money;
    private int balance;

    public Withdraw(Account account, int money) {
        super();
        this.account = account;
        this.money = money;
    }

    @Override
    public void run() {
        if (account.getMoney() - money < 0) {
            return;
        }
        try {
            Thread.sleep(100);  //模拟网络延时
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        balance = account.getMoney() - money;
        account.setMoney(balance);
        System.out.println(Thread.currentThread().getName() + "取了" + money + "---->账户余额为:" + balance);
    }

}

会出现以上两种结果,都是错误的。


 

并发:指同一个对象被多个线程同时操作。

并发可能会导致数据不一致,存在线程安全等问题。

解决此问题可以使用synchronized关键字修饰方法(锁的是this对象) 或者 代码块

如下解决上面的不同步问题  采用的是synchronized代码块  指定要锁的对象是哪个

package threadStudy;

/**
 * 模拟线程不安全 存钱取钱
 */

public class SynTest1 {
    public static void main(String[] args) {
        Account account = new Account("王五的银行卡", 1200);
        Withdraw withdraw1 = new Withdraw(account, 800);
        Withdraw withdraw2 = new Withdraw(account, 700);
        Thread t1 = new Thread(withdraw1, "husband");
        Thread t2 = new Thread(withdraw2, "wife");
        t1.start();
        t2.start();
    }
}

// 账户
class Account {
    private String name;
    private int money;

    public Account(String name, int money) {
        this.name = name;
        this.money = money;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

}

// 取钱的线程

class Withdraw implements Runnable {

    private Account account;
    private int money;
    private int balance;

    public Withdraw(Account account, int money) {
        super();
        this.account = account;
        this.money = money;
    }

    @Override
    public void run() {
        if (account.getMoney() <= 0)
            return;
        test();
    }

    private void test() { // 同步关键字加在这里 锁不住 因为默认锁的是this对象 此处即Withdraw对象 应该锁accout对象
        synchronized (account) {
            if (account.getMoney() - money < 0) {
                return;
            }
            try {
                Thread.sleep(100); // 模拟网络延时
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            balance = account.getMoney() - money;
            account.setMoney(balance);
            System.out.println(Thread.currentThread().getName() + "取了" + money + "---->账户余额为:" + balance);
        }
    }

}

推荐使用synchronized代码块  能够实现更细粒度的控制。

posted @ 2019-06-12 11:35  Practical  阅读(181)  评论(0编辑  收藏  举报