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; } }
*先存后取,账户数据正确。负数是因为存取钱是随机数。