ThreadSafe solves the problem of thread safety

Create an implementation class of Runnable interface to implement a ticket selling case

package demo06.ThreadSafe;/*
 *@author wanghongyuan
 *@Create 2021/1/5 8:02
 */
/*
   实现买票案例
 */
public class RunnableImpl implements Runnable{
    
    
    // 定义一个多个线程共享的票源
   private int ticket = 100;


    // 设置线程任务买票
    @Override
    public void run() {
    
    
       // 使用死循环,让卖票操作重复执行
        while (true){
    
    
            // 先判断票是否存在
            if (ticket> 0){
    
    
				// 提高安全问题出现的概率,让程序睡眠
				try{
    
    
				Thread.sleep(mills:10);
                }catch (InterruptedException e){
    
    
					e.printStackTrace();
}// 票存在,卖票,ticket--
                System.out.println(Thread.currentThread().getName()+"正在卖票-->"+ticket+"张票");
                ticket--;
            }
        }

    }
}

Create a main execution ticket selling case.
Through this case, we found that if three threads share a ticket source at the same time, without processing, three threads seize CPU resources at the same time, there will be thread safety issues, and multiple threads will sell at the same time In the case of an identical ticket.

package ThreadDemo;/*
 @Author wanghongyuan
  @Date 2021/1/5 
 
*/
/*
    买票出现了线程安全的问题
    卖出了不存在和重复的票

    解决线程安全问题的第一种方案:使用同步代码块
     格式:
        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

     注意:
        1.通过代码块中的锁对象,可以使用任意的对象。
        2.但是必须保证多个线程使用的锁对象是同一个
        3.锁对象的作用:
            把同步代码块锁住,只让一个线程在同步代码块中执行

 */
public class Demo01ThreadSafe {
    
    
    public static void main(String[] args) {
    
    
        RunnableImpl run = new RunnableImpl();
        Thread T0= new Thread(run);
        Thread T1= new Thread(run);
        Thread T2= new Thread(run);
        T0.start();
        T1.start();
        T2.start();
    }
}


Use synchronized code blocks to solve thread safety issues

package ThreadDemo;/*
 @Author wanghongyuan
  @Date 2021/1/5 
 
*/
/*
    买票出现了线程安全的问题
    卖出了不存在和重复的票

    解决线程安全问题的第一种方案:使用同步代码块
     格式:
        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

     注意:
        1.通过代码块中的锁对象,可以使用任意的对象。
        2.但是必须保证多个线程使用的锁对象是同一个
        3.锁对象的作用:
            把同步代码块锁住,只让一个线程在同步代码块中执行

 */
public class RunnableImpl implements Runnable{
    
    

    private int ticket = 100;
    // 创建一个锁对象
    Object obj = new Object();

    @Override
    public void run() {
    
    
        while (true){
    
    
            // 创建一个同步代码块
            synchronized (obj){
    
    
                if (ticket>0){
    
    
                    try {
    
    
                        Thread.sleep(10);

                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在售票"+ticket+"张");
                    ticket--;
                }
            }
        }
    }
}

Use static methods

package newww;/*
 @Author wanghongyuan
  @Date 2021/1/5 
 
*/
/*
    买票出现了线程安全的问题
    卖出了不存在和重复的票

    解决线程安全问题的第三种方案:使用静态方法
     格式:
        synchronized(锁对象){
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

     注意:
        1.通过代码块中的锁对象,可以使用任意的对象。
        2.但是必须保证多个线程使用的锁对象是同一个
        3.锁对象的作用:
            把同步代码块锁住,只让一个线程在同步代码块中执行

 */
public class RunnableImpl implements Runnable{
    
    

    private static int ticket = 100;
    // 创建一个锁对象
    Object obj = new Object();

    @Override
    public void run() {
    
    
        while (true){
    
    
            payTicketStatic();
        }
    }
/*
    静态的同步方法
    锁对象是谁?
    不能是this
    this是创建对象之后产生的,静态方法优先于对象
    静态方法的锁对象是本类的class属性-->class文件对象(反射)
 */
    public static /*synchronized*/ void payTicketStatic() {
    
    
        while (true){
    
    
            // 创建一个同步代码块 RunnableImpl.class这个也是一个对象。
            synchronized (RunnableImpl.class){
    
    
                if (ticket>0){
    
    
                    try {
    
    
                        Thread.sleep(10);

                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"正在售23票"+ticket+"张");
                    ticket--;
                }
            }
        }
    }
}

Use Lock to solve thread safety issues

package Demo09.Lock;/*
 @Author wanghongyuan
  @Date 2021/1/5 
 
*/

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
    卖票案例出现了线程安全的问题
    卖出了不存在和重复的票

    解决线程安全的问题第四种方案:使用Lock锁

    java.util.concurrent.Locks.Lock接口
    Lock中的方法:
    void lock()获取锁
    void unlock()释放锁
    java.util.concurrent.Locks.ReentrantLock implement lock接口

    使用步骤:
        1.在成员位置创建一个ReentrantLock对象
        2.在可能会出现安全问题的代码前调用lock接口中的方法lock获取锁
        3.在可能会出现安全问题的代码后调用lock接口中的方法unlock释放锁
 */
public class RunnableImpl implements Runnable{
    
    
    private int ticket = 100;
    //1.在成员位置创建一个ReentrantLock对象
    Lock l= new ReentrantLock();
    @Override
    public void run() {
    
    
        while (true){
    
    
            // 2.在可能会出现安全问题的代码前调用lock接口中的方法lock获取锁
            l.lock();
            if (ticket>0){
    
    
                try {
    
    
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName()+"正在1卖第"+ticket+"张票");
                    ticket--;
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }finally {
    
    
                    //  3.在可能会出现安全问题的代码后调用lock接口中的方法unlock释放锁
                    l.unlock();// 无论程序是否异常,都释放锁
                }
            }
        }


       /* while (true){
            // 2.在可能会出现安全问题的代码前调用lock接口中的方法lock获取锁
            l.lock();
            if (ticket>0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票");
                ticket--;
            }
            //  3.在可能会出现安全问题的代码后调用lock接口中的方法unlock释放锁
            l.unlock();

        }*/
    }
}

Guess you like

Origin blog.csdn.net/weixin_41977380/article/details/112211875