上锁,根据操作系统所说的原则,对共享变量上锁,对临界区上锁。谁访问临界资源?就给谁上锁
同步监视器,它上锁的对象。
1.用关键字给方法上锁
2.用synchronized代码块上锁
默认上锁对象:this,指向自身。就是调用这个方法的对象,给他上锁。
安全的买票(给方法上锁)
public class SynchronizeTest {
//线程不安全
public static void main(String[] args) {
BuyTicker buyTicker = new BuyTicker();
new Thread(buyTicker,"lhh").start();
new Thread(buyTicker,"jhj").start();
new Thread(buyTicker,"黄牛").start();
}
}
class BuyTicker implements Runnable{
private int ticketNum = 10;
boolean flag = true;
@Override
public void run() {
while(flag){//外部停止方式
try {
buy();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}//对买票上锁,锁的this,this是指当前的对象。
public synchronized void buy() throws InterruptedException {//直接给方法上锁
//判断是否有票
if(ticketNum<=0){
System.out.println(Thread.currentThread().getName()+"票卖完了");
flag = false;
return;
}
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"拿到"+ticketNum--);
}
}
安全的银行(给临界区上锁,)
如果给一个类的方法上锁了,实际上是给this也就是调用方法的这个对象上锁,比如你要是给run()上锁,就相当于你去取钱把银行锁了。但是取钱的人都还在银行里面。所以是要对账户上锁,因为我们逍遥操控的变量就是账户。
public class UnsafeBake {
public static void main(String[] args) {
Account account = new Account("结婚基金",1000);
Draw you = new Draw(account,50,"你");
Draw girlFriend = new Draw(account,100,"女朋友");
you.start();
girlFriend.start();
}
}
class Account{
String name;
int money;
public Account(String name, int money) {
this.name = name;
this.money = money;
}
}
class Draw extends Thread{
Account account;
int drawMoney;
int noMoney;
public Draw(Account account, int drawMoney, String name) {
super(name);
this.account = account;
this.drawMoney = drawMoney;
}
@Override
public void run() {
synchronized (account){
if(account.money-drawMoney<0){
System.out.println("余额不足");
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
account.money = account.money - drawMoney;
noMoney = noMoney +drawMoney;
System.out.println(account.name+"余额为:"+account.money);
System.out.println(this.getName()+"手里的钱"+noMoney);//继承THread可以直接写this
}
}
}
安全的列表
public class UnsafeList {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
new Thread(()->{//lambda表达式
synchronized (list){//上锁临界资源list,下面是临界区操作临界资源的代码
list.add(Thread.currentThread().getName());
}
}).start();
}
try {
Thread.sleep(1000);//如果不让他睡,程序结束的时候线程也结束了一半了,列表元素就不够100
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(list.size());
}
}