多线程(3)

1.为什么使用synchronized和java.util.concurrent.locks.Lock?

1>线程不安全,因为线程是随机的,它可以随机访问你可见的共享变量。如果共享变量被修改,对另一个线程操作来说,它的数据就不准确

2>数据不安全,数据被共享

即共享变量、可见性和原子性

3>指令重排序(as-if-serial)

 

   加锁,是只一个线程可以访问,其他线程等待访问的线程结束,后面的线程由cpu随机分配访问。

*线程状态

线程状态:创建->就绪->运行->死亡

线程从就绪状态被唤醒,运行时,有其他线程正在运行且访问的是它要访问的内容,那么,它会阻塞。

阻塞->就绪

休眠状态:即等待(阻塞)状态

运行时,如果cpu随机分配线程抢占了当前线程的资源,该线程进入就绪状态。

public class Account {

    private long money = 0;//余额
    
    public Account(){}
    
    public long cunQian(int num){//存钱
        money  = money + num;
        return num;
    }
    
    public long quQian(int num){//取钱
         money = money - num;
         return num;
    }
    
    public long getMoney(){
        return money;
    }
}
import java.util.Random;

public class Thread02 extends Thread{

    private Account acc = null;
    public Thread02(Account acc){
        this.acc = acc;
    }
    @Override
    public void run() {
        long cunQian = acc.cunQian(new Random().nextInt(1000));
        System.out.println("存了:"+cunQian+";账户内有:"+acc.getMoney());
        long quQian = acc.quQian(new Random().nextInt(1000));
        System.out.println("取了:"+quQian+";账户内有:"+acc.getMoney());
    }

}

无锁

public class Thread02Main {

    public static void main(String[] args) {
        Account acc = new Account();
        Thread02 t1 = new Thread02(acc);
        Thread02 t2 = new Thread02(acc);
        Thread02 t3 = new Thread02(acc);
        t1.start();
        t2.start();
        t3.start();
        
    }
}

 

*无序且数据错误(效果和有锁比较)

有锁

import java.util.Random;

public class Thread02 extends Thread{

    private Account acc = null;
    public Thread02(Account acc){
        this.acc = acc;
    }
    @Override
    public void run() {
        synchronized (acc) {
            long cunQian = acc.cunQian(new Random().nextInt(1000));
            System.out.println("存了:"+cunQian+";账户内有:"+acc.getMoney());
            long quQian = acc.quQian(new Random().nextInt(1000));
            System.out.println("取了:"+quQian+";账户内有:"+acc.getMoney());
        }
    }

}
public class Account {

    private long money = 0;
    
    public Account(){}
    
    public synchronized long cunQian(int num){//存钱
        money  = money + num;
        return num;
    }
    
    public synchronized long quQian(int num){//取钱
         money = money - num;
         return num;
    }
    
    public long getMoney(){
        return money;
    }
}








*先存后取,账户数据正确。负数是因为存取钱是随机数。
原文地址:https://www.cnblogs.com/zzlcome/p/11085343.html