package com.day5.test;
 
/**
 * User: Json
 * Date: 2021/8/15
 * 线程的同步
 * 解决 多个线程执行的不确定性引起执行结果的不稳定
 * 解决的问题点:
 *  多个线程对数据共享时 会造成操作的不完整性 会破坏数据
 *  比如有3000块钱
 *  你和你女朋友同时取1000 就会出现线程安全问题
 * 解决方式
 * 方式一  同步代码块
 *  synchronized(同步监视器){
 *       //需要被同步的代码
 *  }
 *  说明: 1.操作共享数据的代码 即为需要被同步的代码    -->synchronized 不能包代码多了 也不能包多了
 *         2. 同步监视器 , 俗称: 锁 任何一个类的对象, 都可以充当锁
 *           要求:多个线程必须要共用同一把锁
 *        创建多线程有两种方式
 *        第一种 是继承Thread 类实现
 *        这一种 必须声明一个静态的对象属性 充当锁  如果不是 多线程就用的不是一把锁了
 *        第二种 实现Runnable接口的方法 来实现
 *        这一种 可以直接 声明普通的对象属性 来充当锁
 *        这种 还可以使用 this 充当 对象 就不用声明 一个对象
 *  一定要保证 锁 是唯一的  要么还会存在线程安全问题
 *     //把练习的 卖票程序 synchronized包起来
 * 例:       synchronized (obj){
 *           //  synchronized (this){
 *                 if(num>0){
 *
 *                     System.out.println(java.lang.Thread.currentThread().getName()+"卖票 票号为"+num);
 *                     num--;
 *                 }else{
 *                     break;
 *                 }
 *
 *             }
 * 方式二  同步方法
 * 如果操作共享数据的代码完整的声明在一个方法中 我们就可以把这个方法声明成 同步方法 来解决 线程安全问题
 * 例:  还是使用 练习题中的 卖票的程序 做例子
 * // 把卖票的过程 提取出来给他声明成一个独立的方法 加上synchronized 关键字即可
 *   如果是使用 继承Thread类来实现的多线程  也必须把这个方法声明成静态的 static
 *   使用实现Runnable接口的方法 就不需要了
 *    private synchronized void show(){
 *         if(num>0){
 *
 *             System.out.println(java.lang.Thread.currentThread().getName()+"卖票 票号为"+num);
 *             num--;
 *         }
 *     }
 *
 *
 *   方式一 解决了线程安全问题
 *   但是 在操作代码时 只有一个线程参与 其他线程等待 相当于是一个单线程执行的过程 效率低
 **/
public class Synchronization {
 
}
package com.day6.test;
 
import java.util.concurrent.locks.ReentrantLock;
 
/**
 * User: Json
 * Date: 2021/8/18
 * 解决线程安全问题 方式三   * jdk5.0 新增
 * 1. synchronized 和Lock 的异同
 * 相同:二者都可以解决线程安全问题
 * 不同:synchronized 机制在执行完相应的同步代码以后,自动释放锁
 *      Lock 需要手动启动 结束时也需要手动结束
 * jdk5.0 新增
 **/
public class LockTest implements Runnable{
    private int num=100;
    // 1. 实例化 ReentrantLock
     // 如果 给这个对象 传 true   就是公平模式 一个进程执行一次
   // 确保唯一性 如果使用继承的方式 
    private ReentrantLock lock=new ReentrantLock(true);
    @Override
    public void run() {
        while (true){
            try {
                //2.调用lock;
                lock.lock();
 
                if(num>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖票:"+num);
                    num--;
                }else{
                    break;
                }
 
            }finally {
                //3. 调用解锁方法
                lock.unlock();
 
            }
 
        }
    }
}