@Toc

Lock锁

Lock是一个接口,接口的实现类是ReentrantLock

Lock lock=new ReentrantLock();
try{
   lock.lock();//获得锁
}catch(Exception ex){
     
}finally{
    lock.unlock();   //释放锁
}

实例:两个人向一个共同账户内存钱,用Lock锁来实现线程安全

class Bank implements Runnable {
	private int money = 0;// 账户 0
	private Lock lock = new ReentrantLock();
	public void setMoney() {// 存一次
		try{
			lock.lock(); // 获得锁 
			this.money += 100;
			System.out.println(Thread.currentThread().getName() + "存了100元,余额:" + this.money);
		}catch(Exception e){
			
		}finally{
			lock.unlock();// 释放锁
		}
	}

	@Override
	public void run() {
		for (int i = 1; i <= 3; i++) {
			this.setMoney();
		}
	}
}

public class TestLock1 {
	public static void main(String[] args) {
		Bank bank = new Bank();
		Thread zhangsan = new Thread(bank,"张三");
		Thread lisi = new Thread(bank,"李四");
		zhangsan.start();
		lisi.start();
	}
}

输出:

张三存了100元,余额:100
张三存了100元,余额:200
李四存了100元,余额:300
李四存了100元,余额:400
李四存了100元,余额:500
张三存了100元,余额:600

Lock和synchronized的区别

synchronizedLock
关键字接口
自动获得锁和释放锁调用方法显示的获得锁和释放锁
没有其它的方法调用提供更多的功能

大量的线程争夺资源的情况下用Lock锁

死锁

当多个线程进入循环等待状态就会发生死锁
死锁:两个或两个以上线程在争夺资源的时候,造成了互相等待的现象。
解决:给一个顺序,强制一方 sleep();

class Zhangsan {
	public void say(){
		System.out.println("你给我画,我就给你书");
	}
	public void get(){
		System.out.println("张三获得了画");
	}
}
class Lisi{
	public void say(){
		System.out.println("你给我书,我就给你画");
	}
	public void get(){
		System.out.println("李四获得了书");
	}
}
class ThreadDemo implements Runnable{
	// 创建对象
	private static Zhangsan zhangsan = new Zhangsan();
	private static Lisi lisi = new Lisi();
	public boolean tag = true;// 标记(张三李四线程执行不同代码的标记)
	@Override
	public void run() {
		if(tag == true){// 张三
			synchronized (zhangsan) {
				zhangsan.say();// 你给我画,我就给你书
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (lisi) {
					zhangsan.get();// 获得画
				}
			}
		}else{// 李四
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
			
			synchronized (lisi) {
				lisi.say();// 你给我书,我就给你画
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (zhangsan) {
					lisi.get();// 李四获得了书
				}
			}
		}
		
	}
}
public class TestDeadLock {

	public static void main(String[] args) {
		ThreadDemo zhangsanDemo = new ThreadDemo();
		zhangsanDemo.tag = true;
		ThreadDemo lisiDemo = new ThreadDemo();
		lisiDemo.tag = false;
		
		Thread tzhangsan = new Thread(zhangsanDemo,"张三");
		Thread tlisi = new Thread(lisiDemo,"李四");
		
		tzhangsan.start();
		tlisi.start();
	}

}

输出:

你给我画,我就给你书
张三获得了画
你给我书,我就给你画
李四获得了书

如果run语句这样写,就会进入死锁:

public void run() {
		if(tag == true){// 张三
			synchronized (zhangsan) {
				zhangsan.say();// 你给我画,我就给你书
				try {
					Thread.sleep(1000);//等画
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (lisi) {
					zhangsan.get();// 获得画
				}
			}
		}else{// 李四
//			try {//李四先不上锁,等两秒让张三先拿到画后解锁,从而李四可以拿到书
//				Thread.sleep(2000);
//			} catch (InterruptedException e1) {
//				e1.printStackTrace();
//			}
			
			synchronized (lisi) {
				lisi.say();// 你给我书,我就给你画
				try {
					Thread.sleep(1000);//等书
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (zhangsan) {
					lisi.get();// 李四获得了书
				}
			}
		}
		
	}

上述代码中注释掉了else中强行sleep的语句,输出如下:

你给我画,我就给你书
你给我书,我就给你画

Q.E.D.