@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的区别
synchronized | Lock |
---|---|
关键字 | 接口 |
自动获得锁和释放锁 | 调用方法显示的获得锁和释放锁 |
没有其它的方法调用 | 提供更多的功能 |
大量的线程争夺资源的情况下用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.