zoukankan      html  css  js  c++  java
  • 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();
    }
    }

  • 相关阅读:
    phpcurl使用
    系统常见问题
    java虚拟机CPU占用率过高排查方法
    oracle常用维护SQL
    PPT常用演示技能
    VS快捷键
    微软企业库缓存使用
    Oracle导sql的一个简便方法
    领域驱动设计
    sqluldr2
  • 原文地址:https://www.cnblogs.com/wangyanbin2333/p/13448108.html
Copyright © 2011-2022 走看看