day14 线程5 解决线程安全的方式3:Lock锁 同步机制练习(继承方式)

package com.atguigu.java1;

import java.util.concurrent.locks.ReentrantLock;

/**
* 解决线程安全问题的方式三:Lock锁 --- JDK5.0新增          注意:如果用继承的方式,就要把lock加一个静态: private  static ReentrantLock lock = new ReentrantLock();
*
* 1. 面试题:synchronized 与 Lock的异同?
* 相同:二者都可以解决线程安全问题
* 不同:synchronized机制在执行完相应的同步代码以后,自动的释放同步监视器
* Lock需要手动的启动同步(lock()),同时结束同步也需要手动的实现(unlock())
*
* 2.优先使用顺序(只是从灵活的角度考虑):
* Lock > 同步代码块(已经进入了方法体,分配了相应资源) > 同步方法(在方法体之外)
*
*
* 面试题:如何解决线程安全问题?有几种方式     
*/
class Window implements Runnable{

private int ticket = 100;
//1.实例化ReentrantLock
private ReentrantLock lock = new ReentrantLock();

@Override
public void run() {
while(true){
try{

//2.调用锁定方法lock()
lock.lock();

if(ticket > 0){

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(Thread.currentThread().getName() + ":售票,票号为:" + ticket);
ticket--;
}else{
break;
}
}finally {
//3.调用解锁方法:unlock()
lock.unlock();
}

}
}
}

public class LockTest {
public static void main(String[] args) {
Window w = new Window();

Thread t1 = new Thread(w);
Thread t2 = new Thread(w);
Thread t3 = new Thread(w);

t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");

t1.start();
t2.start();
t3.start();
}
}

 

 

 

 

package com.atguigu.exer;

/**
* 银行有一个账户。
有两个储户分别向同一个账户存3000元,每次存1000,存3次。每次存完打印账户余额。

分析:
1.是否是多线程问题? 是,两个储户线程
2.是否有共享数据? 有,账户(或账户余额)
3.是否有线程安全问题?有 多个线程操作共享数据,肯定有线程安全问题
4.需要考虑如何解决线程安全问题?同步机制:有三种方式。

*/
class Account{
private double balance;

public Account(double balance) {
this.balance = balance;                                        //在构造器中把属性实例化
}

//存钱
public synchronized void deposit(double amt){              //这里用this是因为两个线程用的是同一个Account
if(amt > 0){
balance += amt;

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(Thread.currentThread().getName() + ":存钱成功。余额为:" + balance);
}
}
}

class Customer extends Thread{

private Account acct;

public Customer(Account acct) {
this.acct = acct;                                           //在构造器中把属性Account属性实例化
}

@Override
public void run() {

for (int i = 0; i < 3; i++) {
acct.deposit(1000);
}

}
}


public class AccountTest {

public static void main(String[] args) {
Account acct = new Account(0); //账户初始化 ,假设一开始账户没钱
Customer c1 = new Customer(acct);
Customer c2 = new Customer(acct);

c1.setName("甲");
c2.setName("乙");

c1.start();
c2.start();
}
}

posted @ 2020-09-05 21:19  Light光音  阅读(155)  评论(0编辑  收藏  举报