线程同步问题

多个线程在执行的过程中的不确定性引起执行结构的不稳定,同时多个线程对同一数据的共享操作,造成操作的不完整性,破坏数据。
当某个线程在操作车票过程中,尚未操作完成时,其他线程也参与进来,操作车票,使车票的数据共享,出现线程安全问题。
那么可以通过同步代码块和同步方法的方式来解决线程安全问题,实现线程的同步。

方式 1 . 同步代码块
1.1通过多线程继承方式实现代码块同步机制

public class ThreadTest extends Thread {
    public static void main(String[] args) {
        // 实例化窗口一对象
        SaleTicket myThread1=new SaleTicket ();
        // 实例化窗口二对象
        SaleTicket myThread2=new SaleTicket ();
        // 实例化窗口三对象
        SaleTicket myThread3=new SaleTicket ();
        // 窗口一的调用
        myThread1.start();
        // 窗口二的调用
        myThread2.start();
        // 窗口三的调用
        myThread3.start();
        
    }
}
class SaleTicket extends Thread{
    // 定义类的对象,同步监视器,充当锁
    public static Object obj=new Object();
    // 定义静态变量,实现数据共享
    public  static int ticket=100;
    @Override
    public void run() {
        while (true){
        // 使用synchronized,包含被同步的代码
            synchronized (obj){
                if(ticket>0){
                    try {
                        // 调用睡眠方法,进行try-catch处理 
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖票,票号为"+ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
}

1.2通过实现Runnable接口方式实现代码块同步机制

class SaleTicket implements Runnable{
    private  int ticket=100;
    // 定义监视器类
    Object obj=new Object();
    @Override
    public void run() {
        while (true){
        // synchronized同步机制,包含被同步代码
            synchronized (obj){
                if(ticket>0){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"卖票,票号为"+ticket);
                    ticket--;
                }else{
                    break;
                }
            }
        }
    }
}
public class windowTest1 {
    public static void main(String[] args) {
        // 实例化saleTicket对象
        SaleTicket saleTicket=new SaleTicket ();
        // 创建Thread类的对象,传递对象值
        Thread test=new Thread(saleTicket);
        Thread test1=new Thread(saleTicket);
        Thread test2=new Thread(saleTicket);
        // 设置窗口名
        test.setName("窗口1");
        test1.setName("窗口2");
        test2.setName("窗口3");
        // 窗口一的调用方法
        test.start();
        // 窗口二的调用
        test1.start();
        // 窗口三的调用
        test2.start();
    }

}

方式 2 . 同步方法
2.1多线程继承方式和同步方法结合,实现同步机制

public class WindowTest4 {
    public static void main(String[] args) {
         // 实例化窗口一对象
        SaleTicket myThread1=new SaleTicket ();
        // 实例化窗口二对象
        SaleTicket myThread2=new SaleTicket ();
        // 实例化窗口三对象
        SaleTicket myThread3=new SaleTicket ();
        // 窗口一的调用
        myThread1.start();
        // 窗口二的调用
        myThread2.start();
        // 窗口三的调用
        myThread3.start();
    }
}

class SaleTicket extends Thread{
    public  static int ticket=100;
    @Override
    public void run() {
        while (true){
        // 调用show方法
            show();
        }
    }
    // 通过 static show方法,实现synchronized,这里不再需要同步监视器
    private static synchronized void show(){
        if(ticket>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"卖票,票号为"+ticket);
            ticket--;
        }
    }
}

2.2多线程实现Runnable接口方式和同步方法结合,实现同步机制

class Window1 implements Runnable {
    private int ticket = 100;
    @Override
    public void run() {
        while (true) {
        // 调用show方法
        show();
        }
    } 
    // 通过show方法,实现synchronized 
    public synchronized void show() {
            if (ticket > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "卖票,票号为" + ticket);
                ticket--;
            }
      }
}

public class windowTest3 {
    public static void main(String[] args) {
         // 实例化saleTicket对象
        SaleTicket saleTicket=new SaleTicket ();
        // 创建Thread类的对象,传递对象值
        Thread test=new Thread(saleTicket);
        Thread test1=new Thread(saleTicket);
        Thread test2=new Thread(saleTicket);
        // 设置窗口名
        test.setName("窗口1");
        test1.setName("窗口2");
        test2.setName("窗口3");
        // 窗口一的调用方法
        test.start();
        // 窗口二的调用
        test1.start();
        // 窗口三的调用
        test2.start();
    }
}

总结:
1.在非静态的同步代码块中,同步监视器可以是this,对于静态的同步代码块中,同步监视器可以是当前类本身

 private  int ticket=100;
    @Override
    public void run() {
        while (true){
        // 非静态方法中,可以使用this
            synchronized (this){
                if(ticket>0){
                // 被同步的代码
            }
      }
    public  static int ticket=100;
    @Override
    public void run() {
       while (true){
         // 静态方法中是当前类本身,不在定义同步监视器类的对象
         synchronized (myThread1.class){
            if(ticket>0){
              // 被同步的代码
            }
      }

2.在同步方法中仍然设计到同步监视器,在这里我们不需要在显示的声明

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值