线程之同步

2020-09-28  本文已影响0人  是归人不是过客

t1和t2

异步编程模型:t1线程执行t1的,t2线程执行t2的
同步编程模型:t1线程和t2线程执行,当t1线程必须等t2线程执行以后,t1线程才能执行

什么时候要同步那?为什么要引入线程同步那?

1、为了数据的安全,暂时不考虑效率。

线程同步机制使程序变成了(等同)单线程

2、什么条件下要使用线程同步?

第一:必须是多线程环境

第二:多线程共享同一个数据

第三:共享的数据涉及到修改操作

栗子:

一下程序演示取款的栗子,不使用线程同步机制,多线程同时堆同一个账户进行取款操作,会出现什么问题?

测试类:

class Test {
    public static void main(String[] args){
        // 创建一个公共的账户
        Account1 act = new Account1("hl", 5000.0);
        
        // 创建线程对同一账户取款
        Porcessor p = new Porcessor(act);
        
        Thread t1 = new Thread(p);
        Thread t2 = new Thread(p);
        
        t1.start();
        
        t2.start();
        
    }
}

抽象线程

class Porcessor implements Runnable{
    // 账户
    Account1  act;
    Porcessor(Account1 act) {
        this.act = act; 
    };
    @Override
    public void run() {
        // TODO Auto-generated method stub
        act.withdraw(1000.0);
        System.out.println("取款成功1000,余额" + act.getBalance());
    }
}

账户

class Account1{
    private String actno;
    
    private double balance;
    
    public Account1() {}
    public Account1(String actno,double balance) {
        this.actno = actno;
        this.balance = balance;
    }
    
    public String getActno() {
        return actno;
    }
    
    public void setActno(String actno) {
        this.actno = actno;
    }
    
    public double getBalance() {
        return balance;
    }
    
    public void setBalance(double balance) {
        this.balance = balance;
    }
    public void withdraw(double money) {
        double after = balance - money;
        
        // 延迟
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        // 更新
        this.setBalance(after);
    }
}

输出:

取款成功1000,余额4000.0
取款成功1000,余额4000.0

这是发现了异步的问题。

详解synchronized(对象锁)

第一种:

public void withdraw(double money) {
        // 把同步代码放在同步语句块中
        /*
         原理:t1线程和t2线程
         t1线程执行到此地,遇到了synchronized关键字,就会去找this的对象锁,
         如果找到this对象锁,则进入同步语句块中执行程序,当同步语句块中的代码结束后,t1线程归还this的对象锁
         
         在t1线程执行同步语句块的过程中,如果t2线程也过来执行一下代码,也遇到synchronized关键字,所以也去找this的对象锁,
         但是该对象被t1线程持有,只能在这等待this对象的归还。
         * */
        synchronized(this) {
            double after = balance - money;
            
            // 延迟
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            // 更新
            this.setBalance(after);
        }
    }
}

输出:

取款成功1000,余额4000.0
取款成功1000,余额3000.0

第二种:

// synchronized关键字添加成员方法上,线程拿走的也是this的对象锁
    public synchronized void withdraw(double money) {
            double after = balance - money;
            
            // 延迟
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            // 更新
            this.setBalance(after);
        }
}

我们发现第一种方法更加精细。

上一篇 下一篇

猜你喜欢

热点阅读